Menu

Go言語の型変換:intとstringの相互変換、strconvの使い方

Goで型を変換する方法を解説します。strconvによるintから文字列、文字列からintへの変換、浮動小数点数から整数への変換、T(v)による数値の変換、byteとrune、string(65)の罠、そして変換エラーの扱いまで。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

Goは型を暗黙に変換しません。互換性のある型どうしは T(v) で、数値とテキストの間は strconv パッケージで変換します。最もよく検索される2つの変換は次のとおりです。

strconv.Itoa(「integer to ASCII」)は int を10進のテキストに整形します。strconv.Atoi(「ASCII to integer」)はテキストを int に解析し、テキストが有効な数値でなければエラーを返します。そのエラーは必ずチェックしてください。

T(v)による変換

Goの変換の構文は、変換先の型の名前を使った関数呼び出しのように見えます。使えるのは次の3つの場面です。

  1. 数値型どうし(intint64float64uint8 など)
  2. string[]byte または []rune の間
  3. 基底型が同じ型どうし(Celsiusfloat64

結果をよく見てください。

  • int(3.9)3int(-3.9)-3 です。変換は ゼロ方向に切り捨て ます。四捨五入はしません。挙動を選ぶには、先に math.Roundmath.Floormath.Ceil を使います。math.Round は0.5をゼロから遠い方向に丸めるので、-3.5-4 になります。
  • uint8(300)44 です。下位8ビットだけが残るからです(300から256を引いた値)。int8(200)-56 になるのも同じ理由です。エラーもpanicもありません。
  • Celsiusfloat64 は基底型が同じなので自由に変換できますが、明示的に書く必要があります。

値をわざと変数に入れているのには理由があります。定数だと、同じ変換がコンパイルできません。

定数はチェックされ、変数はされない

収まらない定数を変換するとコンパイルエラーになります。同じ値の変数を変換すると、何も言わずに折り返します。

fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8

整数でない定数を整数型に変換するのも拒否されますが、同じ値の変数なら切り捨てられます。

./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int

浮動小数点数の値が変換先の整数型の範囲外にある場合(たとえば int64(1e20))、結果は実装依存です。たとえばamd64とarm64では異なる答えになります。信頼できない値は、変換する前に範囲をチェックしてください。

数値を文字列に変換する

変換元関数結果
intstrconv.Itoa(n)strconv.Itoa(-7)"-7"
int64strconv.FormatInt(n, base)strconv.FormatInt(255, 16)"ff"
uint64strconv.FormatUint(n, base)strconv.FormatUint(5, 2)"101"
float64strconv.FormatFloat(f, fmt, prec, 64)strconv.FormatFloat(3.14159, 'f', 2, 64)"3.14"
boolstrconv.FormatBool(b)strconv.FormatBool(true)"true"
何でもfmt.Sprint(v)fmt.Sprint(3.5)"3.5"
何でも(書式付き)fmt.Sprintf(format, v)fmt.Sprintf("%05d", 42)"00042"

FormatFloat は、書式を表すバイト(固定小数点の 'f'、指数表記の 'e'、短いほうを選ぶ 'g')、精度(-1 は「正確に往復できる最小の桁数」)、元の浮動小数点数のビットサイズ(64または32)を受け取ります。

strconvfmt.Sprint より高速です。fmt.Sprint は値をインターフェースに包み、fmtの汎用的な整形処理を通るからです。ホットなループではこの差が表れますが、たまに変換する程度なら読みやすいほうを選べば十分です。

文字列を数値に変換する

変換先関数戻り値
intstrconv.Atoi(s)int, error
任意の符号付き整数strconv.ParseInt(s, base, bitSize)int64, error
任意の符号なし整数strconv.ParseUint(s, base, bitSize)uint64, error
浮動小数点数strconv.ParseFloat(s, bitSize)float64, error
真偽値strconv.ParseBool(s)bool, error

ParseInt は常に int64 を返します。bitSize 引数(0、8、16、32、64)は受け付ける範囲を決めるので、小さい型に変換しても結果が収まることが保証されます。base が0だと「接頭辞から推測する」という意味になり、0x1f0o170b1011_000 がどれも解析できます。

出力からわかることは次のとおりです。

  • " 42" は失敗します。Atoi が受け付けるのは省略可能な符号と数字だけです。bufio からの入力はたいてい \n で終わるので、取り除いてください。
  • "4.2"Atoi では無効です。小数には ParseFloat を使います。
  • 範囲外のエラーのとき、ParseInt は収まる最大の値(int8 なら 127)をエラーと一緒に返します。エラーがnilでないときは値を使わないでください。
  • エラーは strconv.ErrSyntaxstrconv.ErrRange をラップした *strconv.NumError の値なので、errors.Is で区別できます。

ParseBool1tTTRUEtrueTrue と、それに対応するfalseの形を受け付けます。"yes""on" はエラーです。

string(65)の罠

整数を string に変換しても数字にはなりません。そのUnicodeコードポイントを持つ文字になります。

n := 65
s := string(n) // "A", not "65"

コンパイラは受け付けますが、go vet が報告します。

./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits

本当に文字がほしいなら、ルーンを使ってそう書きます:string(rune(n))。数値をテキストにしたいなら strconv.Itoa(n) を使います。runebytestring に変換するのは問題なく、よく使われます。

文字列、バイト、ルーン

string[]byte[]runeT(v) で相互に変換できます。文字列は変更できず、スライスは変更できるので、どの変換もデータをコピーします。

文字単位でインデックスを使ったり変更したりするときは []rune に、I/O、ハッシュ計算、バイト単位の編集には []byte に変換します。UTF-8の詳細はルーンとバイトのページで扱っています。

変換と型アサーションの違い

変換は、ある具体的な型の値を別の具体的な型に変えるものです。インターフェース(anyerrorio.Reader)から具体的な値を取り出すのは、型アサーションという別の操作です。

var v any = 42

n := v.(int)       // type assertion: v holds an int, give it to me
f := float64(n)    // conversion: int to float64
// f := float64(v) // compile error: cannot convert v (variable of interface type any)
//                  // to type float64: need type assertion

先にアサーションし、それから変換します。カンマok形式の n, ok := v.(int) を使えば、型が違ったときのpanicを避けられます。

早見表

やりたいことコード
intを文字列にstrconv.Itoa(n)
int64を文字列にstrconv.FormatInt(n, 10)
文字列をintにn, err := strconv.Atoi(s)
文字列をint64にn, err := strconv.ParseInt(s, 10, 64)
文字列をfloat64にf, err := strconv.ParseFloat(s, 64)
float64を文字列にstrconv.FormatFloat(f, 'f', -1, 64)
float64をintにint(f)(切り捨て)または int(math.Round(f))
intをfloat64にfloat64(n)
文字列を[]byteに[]byte(s)
[]byteを文字列にstring(b)
runeを文字列にstring(r)
boolを文字列にstrconv.FormatBool(b)
任意の値を文字列にfmt.Sprint(v)

よくある質問

Goでintを文字列に変換するには?

strconv.Itoa(n) を使います:strconv.Itoa(42)"42" を返します。int64 なら strconv.FormatInt(n, 10) を使います。fmt.Sprint(n) もどんな型にも使えますが、遅くなります。string(n) と書いてはいけません。n がUnicodeのコードポイントとして扱われ、string(65)"A" になります。

Goで文字列をintに変換するには?

数値とエラーを返す strconv.Atoi を使います。

n, err := strconv.Atoi("42")
if err != nil {
	// not a valid integer
}

サイズや基数を指定するなら、int64 を返す strconv.ParseInt(s, 10, 64) を使います。Atoiは空白を取り除かないので " 42" はエラーになります。先に strings.TrimSpace を呼んでください。

Goでキャストするには?

Goでは変換(conversion)と呼び、構文は T(v) です:float64(n)int(f)[]byte(s)。数値型どうし、文字列とbyteやruneのスライスの間、そして基底型が同じ型どうしで使えます。テキストの解析はしないので、"42"42 にするには strconv が必要です。インターフェースから具体的な型を取り出すのは変換ではなく型アサーション v.(T) です。

Goでfloatをintに変換するには?

int(f) はゼロ方向に切り捨てます:int(3.9)3int(-3.9)-3 です。四捨五入するなら int(math.Round(f)) を使います。浮動小数点数が整数型の範囲外だと結果は実装依存になるので、値が入力から来る場合は先に範囲をチェックします。

なぜGoのstring(65)は"A"を返すのですか?

整数を string に変換すると、Unicodeのコードポイントとして解釈されます。65は A のコードポイントです。go vet はこれを conversion from int to string yields a string of one rune, not a string of digits として報告します。"65" がほしいなら strconv.Itoa(65) を使います。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める