The range above the {} interface that stores the fragment

Given a scenario in which you have a function that takes t interface{} . If it is determined that t is a slice, how do I range over this slice? I will not know the input type, for example []string , []int or []MyType , at compile time.

 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 Example: http://play.golang.org/p/DNldAlNShB

+66
reflection slice go go-reflect
Dec 24 '12 at 21:28
source share
3 answers

Well, I used reflect.ValueOf , and then if it's a fragment, you can call the Len() and Index() value to get the len slice and element in the index. I don’t think you can use a range for this.

 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 Example: http://play.golang.org/p/gQhCTiwPAq

+98
Dec 24 '12 at 22:05
source share

You do not need to use reflection if you know what types to expect. You can use a type switch , like so:

 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) } } } 

Check out the code at the playground .

+8
Jun 11 '18 at 16:48
source share

there is one exception to the way the {} interface behaves, @Jeremy Wall has already given a pointer. if the transmitted data is initially defined as [] 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) } } } 

exit:

 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] 

try this

0
Apr 07 '19 at 21:01
source share



All Articles