Подтвердить что ты не робот

Диапазон над интерфейсом {}, который хранит фрагмент

Учитывая сценарий, в котором у вас есть функция, которая принимает 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

4b9b3361

Ответ 1

Ну, я использовал 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

Ответ 2

Вам не нужно использовать рефлексию, если вы знаете, какие типы ожидать. Вы можете использовать переключатель типа, например так:

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

Проверьте код на детской площадке.

Ответ 3

есть одно исключение из того, как ведет себя интерфейс {}, @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]

попробуй это