Goでinterface{}をstringに変換する方法を紹介します。

目次

方法1:型アサーション

1つ目は、型アサーションを用いる方法です。
この方法は、interface{}にstringが入っている場合のみ有効です。
下記のように、 変数名.(型)とするとinterfaceだったものの型が断定されます。
なので、変数 result はstring型になっています。

value := interface{}("test")
result := value.(string)

しかし、interface{}にintが入っている場合はpanicを起こしてしまいます。
これは、型アサーションで断定したものが違うためです。
「お前は、ピーマンだ!」
「いえ、パプリカですけど?」
「ふぇぇぇえぇえ(panic)」 的な感じですね。

value := interface{}(11)
result := value.(string) // panic

方法2:switchで型判別し変換

2つ目は、switchで型判別し変換する方法です。
下記のような関数を作って変換します。

func toString(v any) string {
	switch v.(type) {
	case string:
		return v.(string)
	case int:
		return fmt.Sprintf("%d", v)
	case float64:
		return fmt.Sprintf("%g", v)
	case []byte:
		return fmt.Sprintf("%s", v)
	default:
		return ""
	}
}

こうすれば、下記のように map[string]interface{} みたいなものでも型を気にせず変換できます。

func toString(v any) string {
	switch v.(type) {
	case string:
		return v.(string)
	case int:
		return fmt.Sprintf("%d", v)
	case float64:
		return fmt.Sprintf("%g", v)
	case []byte:
		return fmt.Sprintf("%s", v)
	default:
		return ""
	}
}
func main() {
	values := map[string]interface{}{
		"int":    int(10),
		"float":  float64(10),
		"string": string("hello"),
		"byte":   []byte("hello"),
	}

	for i, v := range values {
		fmt.Printf("%s:%s\n", i, toString(v))
	}
}

ですが、この方法はswitchで準備した型がなければ追加しなければなりません。
加えて、こういった処理が必要になるたび十数行コードを書くのは面倒ですね。

方法3:fmt.Sprintfを使って変換

3つ目の方法は、fmt.Sprintfを使う方法です。 []byte以外ならだいたいこれでStringに変換できます。

import (
	"fmt"
	"github.com/harakeishi/gats"
)
func main() {
	values := map[string]interface{}{
		"int":    int(10),
		"float":  float64(10),
		"string": string("hello"),
		"byte":   []byte("hello"),
	}

	for i, v := range values {
		result := fmt.Sprintf("%v", v)
		fmt.Println(result)
	}
}

方法4:gatsパッケージを使って変換(おすすめ)

4つ目の方法は、gatsというパッケージを使用する方法です。
gatsは、go any to stringの略でGoの基本型で宣言されているinterface{}をstringに変換する関数を提供します。

import (
	"fmt"
	"github.com/harakeishi/gats"
)
func main() {
	values := map[string]interface{}{
		"int":    int(10),
		"float":  float64(10),
		"string": string("hello"),
		"byte":   []byte("hello"),
	}

	for i, v := range values {
		result, _ := gats.ToString(v)
		fmt.Printf("%s:%s\n", i, result)
	}
}

gatsの中身でやっていることは2つ目の方法ですが、自分で数十行書かなくてよくなっているので、Goの基本型で宣言されているものを変換するのには便利だと思います。

終わりに

今回は、Goでinterface{}をstringに変換する方法を紹介しました。
interface{}からstringに変換する方法を調べた際、結構型アサーションして変換するとかswitch文で分岐してそれぞれに合った方法で変換するとかは見つかったのですが、gatsのようにパッケージ化したというものは見つけられませんでした。 調べた方法で解決できるのはいいのですが、シンプルにより記述量少なく解決できる(なんなら変換の責務を外部に任せられる)方法があればいいなと思ったので今回パッケージ化しました。 このパッケージが少しでも世の人のためになればうれしいです。