t interface{}
を受け入れる関数があるシナリオを考えます。 t
がスライスであると判断された場合、そのスライス上でrange
を実行するにはどうすればよいですか?コンパイル時に、[]string
、[]int
、または[]MyType
などの着信タイプがわかりません。
func main() {
data := []string{"one","two","three"}
test(data)
moredata := []int{1,2,3}
test(data)
}
func test(t interface{}) {
switch reflect.TypeOf(t).Kind() {
case reflect.Slice:
// how do I iterate here?
for _,value := range t {
fmt.Println(value)
}
}
}
Go Playgroundの例: http://play.golang.org/p/DNldAlNShB
まあ私は_reflect.ValueOf
_を使用し、それがスライスである場合、値でLen()
とIndex()
を呼び出してスライスと要素のlen
を取得できますインデックスで。これを行うために範囲操作を使用できるとは思わない。
_package main
import "fmt"
import "reflect"
func main() {
data := []string{"one","two","three"}
test(data)
moredata := []int{1,2,3}
test(moredata)
}
func test(t interface{}) {
switch reflect.TypeOf(t).Kind() {
case reflect.Slice:
s := reflect.ValueOf(t)
for i := 0; i < s.Len(); i++ {
fmt.Println(s.Index(i))
}
}
}
_
Go Playgroundの例: http://play.golang.org/p/gQhCTiwPAq
どのタイプが期待できるかを知っている場合、リフレクションを使用する必要はありません。次のように type switch を使用できます。
package main
import "fmt"
func main() {
loop([]string{"one", "two", "three"})
loop([]int{1, 2, 3})
}
func loop(t interface{}) {
switch t := t.(type) {
case []string:
for _, value := range t {
fmt.Println(value)
}
case []int:
for _, value := range t {
fmt.Println(value)
}
}
}
interface {}の動作には例外が1つあります。@ Jeremy Wallは既に指摘しています。渡されたデータが最初に[] interface {}として定義されている場合。
package main
import (
"fmt"
)
type interfaceSliceType []interface{}
var interfaceAsSlice interfaceSliceType
func main() {
loop(append(interfaceAsSlice, 1, 2, 3))
loop(append(interfaceAsSlice, "1", "2", "3"))
// or
loop([]interface{}{[]string{"1"}, []string{"2"}, []string{"3"}})
fmt.Println("------------------")
// and of course one such slice can hold any type
loop(interfaceSliceType{"string", 999, map[int]string{3: "three"}})
}
func loop(slice []interface{}) {
for _, elem := range slice {
switch elemTyped := elem.(type) {
case int:
fmt.Println("int:", elemTyped)
case string:
fmt.Println("string:", elemTyped)
case []string:
fmt.Println("[]string:", elemTyped)
case interface{}:
fmt.Println("map:", elemTyped)
}
}
}
出力:
int: 1
int: 2
int: 3
string: 1
string: 2
string: 3
[]string: [1]
[]string: [2]
[]string: [3]
------------------
string: string
int: 999
map: map[3:three]