[]T
Go が暗黙的にに変換する[]interface{}
のに、T
に変換しないのはなぜか不思議ですinterface{}
。この変換について、私が見逃している重要な点があるのでしょうか?
例:
func foo([]interface{}) { /* do something */ }
func main() {
var a []string = []string{"hello", "world"}
foo(a)
}
go build
文句を言う
関数の引数で (type []string) を type []interface {} として使用することはできません
そして、それを明示的にやろうとすると、同じことがb := []interface{}(a)
起こる。
(type []string) を type []interface {} に変換できません
そのため、この変換が必要になるたびに (頻繁に発生するようです)、次のような操作を実行しています。
b = make([]interface{}, len(a), len(a))
for i := range a {
b[i] = a[i]
}
これを行うより良い方法、またはこれらの変換を支援する標準ライブラリ関数はありますか? たとえば、int または文字列のリストを受け取ることができる関数を呼び出すたびに、4 行の余分なコードを書くのは、少しばかげているように思えます。
ベストアンサー1
Go では、構文で複雑またはコストのかかる操作を隠さないという一般的なルールがあります。
a をstring
an に変換するにはinterface{}
、O(1) 時間かかります。スライスは 1 つの値のままなので、a を[]string
anに変換するのも O(1) 時間かかります。ただし、スライスの各要素を an に変換する必要があるため、a を an に変換するには O(n) 時間かかります。interface{}
[]string
[]interface{}
interface{}
このルールの唯一の例外は、文字列の変換です。 a をstring
a または[]byte
aに変換する場合[]rune
、変換は「構文」であるにもかかわらず、Go は O(n) で動作します。
この変換を自動的に行う標準ライブラリ関数はありません。ただし、最善の選択肢は、質問で示したコード行を使用することです。
b := make([]interface{}, len(a))
for i := range a {
b[i] = a[i]
}
それ以外の場合は、 を使用して作成することもできますreflect
が、3 行のオプションよりも遅くなります。リフレクションを使用した例:
func InterfaceSlice(slice interface{}) []interface{} {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil
}
ret := make([]interface{}, s.Len())
for i:=0; i<s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}