3

I have a struct A, extending ("subclassing") it with struct B, like this:

package main

type A struct {
    x int
}

type B struct {
    A
    y int
}

I want to create a array where I can append A or B to it, so that this code works:

func main() {
    var m [2]B

    m[0] = B { A { 1 }, 2 }
    m[0].x = 0
    m[0].y = 0

    m[1] = A { 3 }
    m[1].x = 0
}

It doesn't. If I create the array of the type B, I get "cannot use struct literal (type A) as type B in assignment". If I try to create the array of the type A, I get the the same error (just with the types reversed).

So my question is: which type should the array be?

2 Answers 2

3

You could use struct values. For example,

package main

import "fmt"

type A struct {
    x int
}

type B struct {
    A
    y int
}

func main() {
    var m []interface{}
    m = append(m, B{A{1}, 2})
    m = append(m, A{3})
    fmt.Println(m[0], m[1])
    if b, ok := m[0].(B); ok {
        b.x = 0
        b.y = 0
        m[0] = b
    }
    if a, ok := m[1].(A); ok {
        a.x = 0
        m[1] = a
    }
    fmt.Println(m[0], m[1])
}

Output:
{{1} 2} {3}
{{0} 0} {0}

Or, you could use struct pointers. For example,

package main

import "fmt"

type A struct {
    x int
}

type B struct {
    A
    y int
}

func main() {
    var m []interface{}
    m = append(m, &B{A{1}, 2})
    m = append(m, &A{3})
    fmt.Println(m[0], m[1])
    if b, ok := m[0].(*B); ok {
        b.x = 0
        b.y = 0
    }
    if a, ok := m[1].(*A); ok {
        a.x = 0
    }
    fmt.Println(m[0], m[1])
}

Output:
&{{1} 2} &{3}
&{{0} 0} &{0}
Sign up to request clarification or add additional context in comments.

1 Comment

Ok, thank you! I suppose my question now is: is this idiomatic? Am I doing in the "Go" way? I ask this because it seems a lot of code just to access the field of a "superstruct".
2

You'll want to define the array type to interface{} rather than B. Then you can store both types in there. That's the only way to accomplish this. If both types implement a specific interface, then you can type to that instead of the generic interface{}

3 Comments

It doesn't work. Using var m [2]interface{} gets me test.go:16: m[0].x undefined (type interface { } has no field or method x) test.go:17: m[0].y undefined (type interface { } has no field or method y) test.go:20: m[1].x undefined (type interface { } has no field or method x)
You'll have to do a type cast when you pull it out, see here: golang.org/doc/go_spec.html#Type_assertions
Then what'd be the correct syntax to change a field? I tried to replace m[0].x = 0 for m[0].(B).x = 0, but now I get "cannot assign to m[0].(B).A.x".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.