-1

Is it possible to differentiate between []interface{} and interface{} in a switch case?

Trying to create a decoding function in which you can pass in different types and then a switch case determines the type and then proceed to decode that particular type. Although I am having issues when the type passed is a []interface{}.

I have been experimenting with the reflect package but no luck thus far. See code snippet and playground link below.

package main

import (
    "fmt"
    "math/big"
)

type Test struct {
    t      interface{}
}

func main() {
    testVar1 := big.NewInt(0)
    testVar2 := int64(1)
    testVar3 := []byte("test")
    testVar4 := true
    testVar5 := []int{1, 2, 3, 4}
    var testVar6 Test

    Issue(testVar1)
    Issue(testVar2)
    Issue(testVar3)
    Issue(testVar4)
    Issue(testVar5)
    Issue(testVar6)
}

func Issue(t interface{}) {
    switch t.(type) {
    case *big.Int:
        fmt.Println("*big.Int")
    case int8, int16, int32, int64:
        fmt.Println("int8, int16, int32, int64")
    case []byte:
        fmt.Println("[]byte")
    case bool:
        fmt.Println("bool")
    case []interface{}:
        fmt.Println("how to get testVar5 to print here")
        fmt.Println("[]interface{}")
    case interface{}:
        fmt.Println("interface{}")
    default:
        fmt.Println("unsupported type")
    }
}

Results:

*big.Int
int8, int16, int32, int64
[]byte
bool
interface{}
interface{}

Is there any way to get testVar5 to hit the []interface{} case?

https://play.golang.org/p/U0dJF9CEbTX

dutterbutter
  • 157
  • 1
  • 3
  • 12
  • 1
    This is a very common question and at the moment I can't find the definitive answer, but in short, `[]someType` cannot be used where `[]someInterface` is expected, even if `someType` implements `someInterface`. For this reason, `[]int` does not match `[]interface{}` in your `switch` statement. – Andy Schweig Feb 27 '19 at 18:41
  • 1
    https://stackoverflow.com/a/12994852/965900 – mkopriva Feb 27 '19 at 18:46

2 Answers2

1

you can use the reflect package like this:

package main

import (
    "fmt"
    "math/big"
    "reflect"
)

type Test struct {
    t      interface{}
}

func main() {
    testVar1 := big.NewInt(0)
    testVar2 := int64(1)
    testVar3 := []byte("test")
    testVar4 := true
    testVar5 := []int{1, 2, 3, 4}
    var testVar6 Test

    Issue(testVar1)
    Issue(testVar2)
    Issue(testVar3)
    Issue(testVar4)
    Issue(testVar5)
    Issue(testVar6)
}

func Issue(t interface{}) {
    switch t.(type) {
    case *big.Int:
        fmt.Println("*big.Int")
    case int8, int16, int32, int64:
        fmt.Println("int8, int16, int32, int64")
    case []byte:
        fmt.Println("[]byte")
    case bool:
        fmt.Println("bool")
    case interface{}:
        rt := reflect.TypeOf(t)
        switch rt.Kind() {
        case reflect.Slice:
            fmt.Println("Slice")
        case reflect.Array:
            fmt.Println("Array")
        default:
            fmt.Println("interface{}")
        }
    default:
        fmt.Println("unsupported type")
    }
}
Thomas Milox
  • 96
  • 1
  • 4
0

Is there any way to get testVar5 to hit the []interface{} case?

No. See e.g. https://golang.org/doc/faq#convert_slice_of_interface

Volker
  • 40,468
  • 7
  • 81
  • 87