Search code examples
gostructtypescasting

Can you type assert an anonymous struct?


I want to do something like this:

type Struct1 struct {
    var1 int
}

type i interface {
    display()
}

func (s Struct1) display() {
    fmt.Println(s.var1)
}

func check(i interface{}) {
    i.(Struct1).display()
}

func main() {
    data := struct {
        int
    }{
        2,
    }

    check(interface{}(data))
}

I have a function in an external dependency that accepts and returns interface{} type. That function type asserts a struct(let's say Struct1). The struct has fields that are not exported to I cannot create an instance of it to pass to the function. I know what fields it has, their names and types. Is it possible to send data not of type Struct1 that can be asserted to become Struct1 type.


Solution

  • Can you type assert an anonymous struct?

    Of course you can! But there are limitations.

    Some things that will work:

    1. Assert to a matching anonymous struct:

       x := interface{}(struct { Count int }{Count: 5})
       fmt.Printf("x's count: %d\n", x.(struct{Count int}).Count)
      

      Playground.

    2. Assert to an interface:

       type Fooer interface {
           Foo()
       }
      
       type X struct {}
      
       func (x X) Foo() { fmt.Printf("X Fooed\n") }
      
      
       func main() {
           x := interface{}(struct { X }{ X{} }) // An anonymous struct which embeds X
           x.(Fooer).Foo()
       }
      

      Playground.

    Some things that won't work:

    1. Assert to a matching anonymous struct from another package, with un-exported fields.

       x := url.UserPassword("foo","bar")
       fmt.Printf("Username: %s\n", x.(struct{username string; password string; passwordSet bool}).username)
      

      Playground.