How to check if interface{} is a slice

后端 未结 3 1366
离开以前
离开以前 2021-01-12 03:49

I\'m noob in Go :) so my question may be stupid, but can\'t find answer, so.

I need a function:

func name (v interface{}) {
    if is_slice() {
              


        
相关标签:
3条回答
  • 2021-01-12 04:05

    In your case the type switch is the simplest and most convenient solution:

    func name(v interface{}) {
        switch x := v.(type) {
        case []MyInterface:
            fmt.Println("[]MyInterface, len:", len(x))
            for _, i := range x {
                fmt.Println(i)
            }
        case MyInterface:
            fmt.Println("MyInterface:", x)
        default:
            fmt.Printf("Unsupported type: %T\n", x)
        }
    }
    

    The case branches enumerate the possible types, and inside them the x variable will already be of that type, so you can use it so.

    Testing it:

    type MyInterface interface {
        io.Writer
    }
    
    var i MyInterface = os.Stdout
    name(i)
    var s = []MyInterface{i, i}
    name(s)
    name("something else")
    

    Output (try it on the Go Playground):

    MyInterface: &{0x1040e110}
    []MyInterface, len: 2
    &{0x1040e110}
    &{0x1040e110}
    Unsupported type: string
    

    For a single type check you may also use type assertion:

    if x, ok := v.([]MyInterface); ok {
        // x is of type []MyInterface
        for _, i := range x {
            fmt.Println(i)
        }
    } else {
        // x is not of type []MyInterface or it is nil
    }
    

    There are also other ways, using package reflect you can write a more general (and slower) solution, but if you're just starting Go, you shouldn't dig into reflection yet.

    0 讨论(0)
  • 2021-01-12 04:08

    From https://blog.golang.org/json

    Decoding arbitrary data

    Consider this JSON data, stored in the variable b:

    b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
    

    Without knowing this data's structure, we can decode it into an interface{} value with Unmarshal:

    var f interface{} err := json.Unmarshal(b, &f) At this point the Go value in f would be a map whose keys are strings and whose values are themselves stored as empty interface values:

    f = map[string]interface{}{
        "Name": "Wednesday",
        "Age":  6,
        "Parents": []interface{}{
            "Gomez",
            "Morticia",
        },
    }
    

    To access this data we can use a type assertion to access f's underlying map[string]interface{}:

    m := f.(map[string]interface{})
    

    We can then iterate through the map with a range statement and use a type switch to access its values as their concrete types:

    for k, v := range m {
        switch vv := v.(type) {
        case string:
            fmt.Println(k, "is string", vv)
        case float64:
            fmt.Println(k, "is float64", vv)
        case []interface{}:
            fmt.Println(k, "is an array:")
            for i, u := range vv {
                fmt.Println(i, u)
            }
        default:
            fmt.Println(k, "is of a type I don't know how to handle")
        }
    }
    

    In this way you can work with unknown JSON data while still enjoying the benefits of type safety.

    0 讨论(0)
  • 2021-01-12 04:16

    icza's answer is correct, but is not recommended by go creators:

    interface{} says nothing

    A better approach may be to define a function for each type you have:

    func name(v MyInterface) {
        // do something
    }
    
    func names(vs []MyInterface) {
        for _, v := range(vs) {
            name(v)
        }
    }
    
    0 讨论(0)
提交回复
热议问题