Biorąc pod uwagę scenariusz, w którym masz funkcję, która akceptuje t interface{}
. Jeśli okaże się, że t
jest to kawałek, jak mam range
go nadrobić?
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)
}
}
}
Przykład Go Playground: http://play.golang.org/p/DNldAlNShB
go
reflection
slice
go-reflect
Nukleon
źródło
źródło
Odpowiedzi:
Cóż, użyłem,
reflect.ValueOf
a następnie, jeśli jest to wycinek, możesz wywołaćLen()
iIndex()
wartość, aby uzyskaćlen
wycinek i element w indeksie. Nie sądzę, abyś mógł użyć zakresu działania, aby to zrobić.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)) } } }
Przykład Go Playground: http://play.golang.org/p/gQhCTiwPAq
źródło
s.Index(i)
zwrócenie wartości,reflect.Value
więc w moim przypadku musiałems.Index(i).Interface()
odwołać się do rzeczywistej wartości.interface{}
? np.moredata := &[]int{1,2,3}
Elem()
aby uzyskać podstawową wartość. np.reflect.TypeOf(reflect.ValueOf(t).Elem().Interface()).Kind()
Nie musisz używać refleksji, jeśli wiesz, jakich typów się spodziewać. Możesz użyć przełącznika typu , na przykład:
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) } } }
Sprawdź kod na placu zabaw .
źródło
array[:]
.jest jeden wyjątek od sposobu, w jaki zachowuje się {} interfejs, @Jeremy Wall dał już wskaźnik. jeśli przekazywane dane są początkowo zdefiniowane jako [] interfejs {}.
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) } } }
wynik:
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]
Wypróbuj to
źródło