« Back to Index

Type check object is an instance of a specific struct

View original Gist on GitHub

Tags: #go

1. main.go

package main

import "fmt"

type Test struct {
	foo int
}

type Foo struct {
}

// we need a function to wrap the switch statement as it only works with interface types, 
// and so we trick the switch statement into thinking it got an interface type by
// having the function accept anything via the empty interface{} type.
//
// NOTE: it's important to realize that if you have a pointer to a struct, 
// then you'll need to define a pointer version case statement to catch it.
func isType(t interface{}) bool {
	switch t.(type) {
	case Test:
		return true
	case Foo:
		return true
	case *Foo:
		return true
	default:
		return false
	}
}

func main() {
	t := Test{5}
	fmt.Println(isType(t))

  	// non-pointer version
	s := Foo{}
	fmt.Println(isType(s))

  	// pointer version
	s2 := &Foo{}
	fmt.Println(isType(s2))
}

2. old.go

package main

import "fmt"

type Test struct {
	foo int
}

type TestA struct {
	Test
}

type TestB struct {
	Test
}

func isTest(t interface{}) string {
	switch t.(type) {
	case TestA:
		return "A"
	case TestB:
		return "B"
	default:
		return "NA"
	}
}

func main() {
	ta := TestA{}
	tb := TestB{}

	// by not setting 'foo' property as part of TestA/TestB instantiation
    // we avoid the "cannot use promoted field" compiler error
    // see: https://gist.github.com/Integralist/b123e4a98bcf232d09216577c29f34a3
	ta.foo = 1
	tb.foo = 2
  
    /*
     a better approach to avoid the "cannot use promoted field" compiler error
     would be to do this...
     
     t := Test{foo: 123}
     ta := TestA{t}
     tb := TestB{t}
    */

	fmt.Printf("%+v\n", ta)
	fmt.Printf("%+v\n", tb)

	fmt.Println(isTest(ta)) // A
	fmt.Println(isTest(tb)) // B
}