こんにちは。Go入門ブログの第29回です。
今回は、Goにおける代表的な標準パッケージの一つであるstrconvパッケージについて解説します。
strconvは、文字列と基本データ型の相互変換機能を提供するパッケージです。
前回解説したstringsパッケージとも相性の良いパッケージですので、あわせて学習しておきましょう。
Contents
Atoi関数とItoa関数
まず導入として、strconvで最もシンプルな文字列と整数の変換を紹介しておきます。
func Atoi(s string) (int, error)
Itoa関数は、引数に指定された数値を文字列に変換して返します。
Atoi関数は、引数に指定された文字列を数値型に変換して返します。
Atoiのみ、2番目の返り値としてerror型を返します。
これらの関数は、変換において10進数の数字とGoのint型を使用します。
単純な整数・文字列の変換ならば、これらの関数を使用するとよいでしょう。
変換時の基数や精度を指定したい場合は、後述のFormatIntやParseIntを使用してください。
サンプルと実行結果は以下の通りです。
package main import ( "fmt" "strconv" ) func main() { // 変換元の文字列 var org string = "123" // 文字列から数値への変換 i, _ := strconv.Atoi(org) // 数値から文字列への変換 s := strconv.Itoa(i) // 出力 fmt.Printf("文字列\"%s\"を数値%dに変換しました\n", s, i) }
文字列”123″を数値123に変換しました
fmt.Printf関数により、変数i・sがそれぞれ数値・文字列に正しく型変換されていることを確認できます。
数値型・論理型から文字列型への変換
他の基本型から文字列型への変換関数は、”Format○○”として実装されています。
○○には変換元の型名が入ります。
FormatBool関数 – 論理型から文字列への変換
strconv.FormatBool関数は、論理型の値を文字列に変換できます。
引数で渡された論理値bが真であれば文字列”true”を、偽であれば文字列”false”を返します。
サンプルと実行結果は以下の通りです。
package main import ( "fmt" "strconv" ) func main() { // 変換元の論理値 var org1 bool = true var org2 bool = false // 論理値から文字列への変換 s1 := strconv.FormatBool(org1) s2 := strconv.FormatBool(org2) // 出力 fmt.Printf("org1: %s,org2: %s\n", s1, s2) }
org1: true,org2: false
FormatInt / FormatUnit関数 – 整数型から文字列への変換
整数型から文字列への変換は、strconv.FormatIntとstrconv.FormatUnitが用意されています。
それぞれ符号付き整数型と符号なし整数型に対応しています。
func FormatUint(i uint64, base int) string
第2引数baseには、整数の文字列表現に使用する基数を指定できます。
baseに10を指定すれば10進数が、2を指定すれば2進数が得られます。
なお、先述のItoa、は内部的にはstrconv.FormatInt(i, 10)を移用しているショートカット関数です
FormatIntで統一することも可能ですが、可能な場合はItoaを使用した方が可読性の面ではよいかもしれません。
サンプルと実行結果は以下の通りです。
package main import ( "fmt" "strconv" ) func main() { // 変換元の数値 var org1 int64 = -123456 var org2 uint64 = 123456 // 数値から文字列への変換 s1base2 := strconv.FormatInt(org1, 2) // 2進数 s1base8 := strconv.FormatInt(org1, 8) // 8進数 s2base10 := strconv.FormatUint(org2, 10) // 10進数 s2base16 := strconv.FormatUint(org2, 16) // 16進数 // 出力 fmt.Printf("%dを2進数で表記: %s\n", org1, s1base2) fmt.Printf("%dを8進数で表記: %s\n", org1, s1base8) fmt.Printf("%dを10進数で表記: %s\n", org2, s2base10) fmt.Printf("%dを16進数で表記: %s\n", org2, s2base16) }
-123456を2進数で表記: -11110001001000000
-123456を8進数で表記: -361100
123456を10進数で表記: 123456
123456を16進数で表記: 1e240
FormatFloat関数 – 小数型から文字列への変換
不動小数点型の値を文字列に変換する場合、strconv.FormatFloat関数を使用します。
この関数は、整数型の変換に比べやや複雑です。
まず、第2引数fmtには、不動小数点数の書式を表す指定子を指定します。
指定可能な定数は、f、e、E、g、G、bのいずれかです。
fmt指定子 | 用法・用途 |
---|---|
f | 実数表現で出力する |
e | 10進数の指数表現で出力する(eは小文字) |
E | 10進数の指数表現で出力する(Eは大文字) |
g | 指数部が大きい場合は%e、それ以外は%fで出力する |
G | 指数部が大きい場合は%E、それ以外は%fで出力する |
b | 2進数の指数表現で出力する |
次に第3引数precには、桁数の制限を指定します。
-1を指定した場合には、文字列化する不動小数点数の表現に必要な桁数が自動で選択されます。
最後に第4引数bitSizeは、文字列化する不動小数点数の精度をビット数(32または64)で指定します。
サンプルと実行結果は以下の通りです。
package main import ( "fmt" "strconv" ) func main() { // 変換元の数値 var org1 float64 = 123.456 var org2 float64 = 123456789.012345 // 数値から文字列への変換 sf := strconv.FormatFloat(org1, 'f', -1, 64) // 実数表現、全桁 se1 := strconv.FormatFloat(org1, 'e', -1, 64) // 10進数の指数表現、全桁 se2 := strconv.FormatFloat(org1, 'E', 2, 64) // 10進数の指数表現、小数部2桁 sg1 := strconv.FormatFloat(org1, 'g', -1, 64) // 実数表現、全桁 sg2 := strconv.FormatFloat(org2, 'G', 4, 64) // 10進数の指数表現、小数部4桁 sb := strconv.FormatFloat(org1, 'b', -1, 64) // 2進数の指数表現、全桁 // 出力 fmt.Printf("%gを実数表現で表記: %s\n", org1, sf) fmt.Printf("%gを10進数の指数表現で表記: %s\n", org1, se1) fmt.Printf("%gを10進数の指数表現で表記: %s\n", org1, se2) fmt.Printf("%gを実数表現で表記: %s\n", org1, sg1) fmt.Printf("%fを10進数の指数表現で表記: %s\n", org2, sg2) fmt.Printf("%gを2進数の指数表現で表記: %s\n", org1, sb) }
123.456を実数表現で表記: 123.456
123.456を10進数の指数表現で表記: 1.23456e+02
123.456を10進数の指数表現で表記: 1.23E+02
123.456を実数表現で表記: 123.456
123456789.012345を10進数の指数表現で表記: 1.235E+08
123.456を2進数の指数表現で表記: 8687443681197687p-46
文字列型から数値型・論理型への変換
文字列型から他の基本型への変換関数は、”Parse○○”として実装されています。
○○には変換先の型名が入ります。
ParseBool関数 – 文字列から論理型への変換
strconv.ParseBool関数は、文字列によって表された真偽値を返します。
真と判別される文字列は、”1″、”t”、”T”、”TRUE”、”true”、”True” の6種です。
偽と判別される文字列は、”0″、”f”、”F”、”FALSE”、”false”、”False”の6種です。
上記12種以外の文字列を渡した場合、2番目の戻り値でエラーが返されます。
サンプルと実行結果は以下の通りです。
package main import ( "fmt" "strconv" ) // strconv.ParseBoolで文字列を論理値に変換する関数 func Atob(org string) { if b, err := strconv.ParseBool(org); err == nil { fmt.Printf("文字列\"%s\"を論理値%vに変換しました\n", org, b) } else { fmt.Printf("文字列\"%s\"は論理値に変換できません\n", org) } } func main() { // 変換関数の実行 Atob("1") Atob("t") Atob("T") Atob("TRUE") Atob("true") Atob("True") Atob("0") Atob("f") Atob("F") Atob("FALSE") Atob("false") Atob("False") Atob("hoge") // 変換不可 }
文字列”1″を論理値trueに変換しました
文字列”t”を論理値trueに変換しました
文字列”T”を論理値trueに変換しました
文字列”TRUE”を論理値trueに変換しました
文字列”true”を論理値trueに変換しました
文字列”True”を論理値trueに変換しました
文字列”0″を論理値falseに変換しました
文字列”f”を論理値falseに変換しました
文字列”F”を論理値falseに変換しました
文字列”FALSE”を論理値falseに変換しました
文字列”false”を論理値falseに変換しました
文字列”False”を論理値falseに変換しました
文字列”hoge”は論理値に変換できません
ParseInt / ParseUint関数 – 文字列から整数型への変換
strconv.ParseIntとstrconv.ParseUnitは、文字列を解析して整数型を返す関数です。
それぞれ符号付き整数型と符号なし整数型に対応しています。
func ParseUint(s string, base int, bitSize int) (uint64, error)
第2引数baseには、FormatInt/FormatUintと同じく基本数を指定します。
第3引数bitSizeには、整数の精度をビット数で指定します。
bitSizeに0を指定した場合、Goプラットフォームのint型/uint型の制度が指定されます。
また、変換元の数値文字列がbitSizeに指定した制度を超える場合、エラーが返されます。
なお、先述のAtoi関数は、Itoa関数と同様に、内部的にはstrconv.ParseInt(s, 10, 0)を移用しているショートカット関数です
サンプルと実行結果は以下の通りです。
package main import ( "fmt" "strconv" ) func main() { // 変換元の文字列 var org1 string = "-101010" var org2 string = "7F4D" // 文字列を数値に変換 i1base2, _ := strconv.ParseInt(org1, 2, 0) // 2進数 i1base8, _ := strconv.ParseInt(org1, 8, 0) // 8進数 i2base10, _ := strconv.ParseInt(org1, 10, 0) // 10進数 i2base16, _ := strconv.ParseUint(org2, 16, 0) // 16進数 // 出力 fmt.Printf("文字列\"%s\"を2進数で数値変換: %d\n", org1, i1base2) fmt.Printf("文字列\"%s\"を8進数で数値変換: %d\n", org1, i1base8) fmt.Printf("文字列\"%s\"を10進数で数値変換: %d\n", org1, i2base10) fmt.Printf("文字列\"%s\"を16進数で数値変換: %d\n", org2, i2base16) // 変換元の数値文字列がbitSizeに指定した制度を超える場合はエラー if _, err := strconv.ParseInt(org1, 10, 3); err != nil { fmt.Printf("桁数が超過したため%sの数値変換に失敗しました\n", org1) } }
文字列”-101010″を2進数で数値変換: -42
文字列”-101010″を8進数で数値変換: -33288
文字列”-101010″を10進数で数値変換: -101010
文字列”7F4D”を16進数で数値変換: 32589
桁数が超過したため-101010の数値変換に失敗しました
ParseFloat関数 – 文字列から小数型への変換
strconv.ParseFloat関数は、実数や指数表現で記述されたを文字列を解析して、浮動小数点型に変換する関数です。
第2引数bitSizeには、浮動小数点数の精度をビット数で指定します。
変換元の文字列がbitSizeに指定した制度で表現可能な範囲を超える場合、エラーが発生します。
サンプルと実行結果は以下の通りです。
package main import ( "fmt" "strconv" ) func main() { // 変換元の文字列 var org1 string = "3.14" var org2 string = "3.1415926535897932384" var org3 string = "1E500" // 文字列を浮動小数点数に変換 f1, _ := strconv.ParseFloat(org1, 64) f2, _ := strconv.ParseFloat(org2, 32) // 指定した制度で丸め // 出力 fmt.Printf("文字列\"%s\"を浮動小数点数に変換: %g\n", org1, f1) fmt.Printf("文字列\"%s\"を浮動小数点数に変換: %g\n", org2, f2) // 変換元の数値文字列がbitSizeに指定した制度を超える場合はエラー if _, err := strconv.ParseInt(org1, 10, 3); err != nil { fmt.Printf("文字列\"%s\"は指定した精度で表現可能な範囲を超過してます\n", org3) } }
文字列”3.14″を浮動小数点数に変換: 3.14
文字列”3.1415926535897932384″を浮動小数点数に変換: 3.1415927410125732
文字列”1E500″は指定した精度で表現可能な範囲を超過してます
終わりに
Goは型定義に厳密な言語であり、言語仕様として暗黙の型変換は排除されています。
このため、今回紹介したstrconvパッケージを用いた型変換が必要になるケースは多くなります。
関数名も統一されておりシンプルな設計ですので、ぜひ使いこなせるようにしておきましょう。