I am working on a demo project to understand GO language. I have defined one interface and 2 struct type. Also, I have defined an array of interfaces. Depending on the user input, I define each element within the array as a type of struct. During the data manipulation, I want to check the type of the struct defined on the array.
I have tried to use reflect, but unfortunately it did not worked. Also other methods on internet did not worked. I received messages such as panic or json cannot Unmarshal.
type Main_interface interface {
}
type Struct1 struct {
Index int
ID int
Name string
}
type Struct2 struct {
Index int
Timestamp string
Temporary_ID int
}
var MyArray []Main_interface
//...
NewStruct1Block := generateStruct1Block(...)
MyArray = append(MyArray, NewStruct1Block)
//...
NewStruct2Block := generateStruct2Block(...)
MyArray = append(MyArray, NewStruct2Block)
UPDATE: I want to be able to check the kind of struct implements the interface at runtime, depending on the user input.
You need to use type assestion as below:
var MyArray []Main_interface
NewStruct1Block := Struct1{}
NewStruct2Block := Struct2{}
MyArray = append(MyArray, NewStruct1Block)
MyArray = append(MyArray, NewStruct2Block)
fmt.Printf("%v", MyArray)
switch t := MyArray[0].(type) {
case Struct1:
fmt.Printf("%v", t)
t.ID = 1
case Struct2:
fmt.Printf("%v", t)
t.Timestamp = "A"
default:
fmt.Print("unknown")
}
Working code here: https://play.golang.org/p/OhpBDJu_q2x
Your array can be heteregenious, that is, it can contain elements of different types. You can't ensure (at compile time) that all elements are of the same type.
That said, you can check a single element using the type cast syntax.
You have three options:
Option 1: Check against a specific type
var unknown Main_Interface = getSomethingSomewhere()
result, ok := unknown.(Struct1);
if ok {
// result has type `Struct1`
}
Option 2: Use a switch statement to cover multiple types (already presented in another answer)
switch t := unknown.(type) {
case Struct1:
// t has type `Struct1` within this block (at compile time)
case Struct2:
// t has type `Struct2` within this block (at compile time)
default:
// neither Struct1 no Struct2
}
Option 3: compare against another type at runtime.
Note that types returned by reflect.TypeOf
are comparable using the ==
operator, as documented here:
https://golang.org/pkg/reflect/#Type
Type values are comparable, such as with the == operator, so they can be used as map keys. Two Type values are equal if they represent identical types.
So we can do something like this:
var s1 Struct1 // empty struct
var s2 Struct2 // empty struct
if reflect.TypeOf(unknown) == reflect.TypeOf(s1) {
// unknown holds an s1 instance
}
But this is obviously not useful when you can just do the compile time check. Instead, you can compare two unknowns to check if they are the same:
var unknown1 Main_Interface = getSomethingSomewhere()
var unknown2 Main_Interface = getSomethingSomewhereElse()
if reflect.TypeOf(unknown1) == reflect.TypeOf(unknown2) {
// they are the same type
}