Home > Mobile >  Accessing specific field of a generic struct passed to a variadic function
Accessing specific field of a generic struct passed to a variadic function

Time:12-21

Say I have a generic struct called foo:

type foo[T any] struct {
    data T
}

I have a variadic function that I want to pass some foos to. They could be any type of foo. My understanding is that because a foo[int] is different to a foo[string], I need to define my ellipsis as type any, like so:

func bar(things ...any) {
    for _, v := range things {
        fmt.Println(v)
    }
}

And this indeed works.

func main() {
    a := foo[string]{"cheese"}
    b := foo[int]{42}

    bar(a, b)
}

My problem is that I want to specifically access the data field in each foo. But if I define bar like this,

func bar(things ...any) {
    for _, v := range things {
        fmt.Println(v.data)
    }
}

the compiler gets understandably upset, since things could be anything and, therefore, there is no guarantee they have the field data.

I know there will be a field called data since I'm always passing foos, but I can't specify that I'll only pass foos, like this,

func bar(things ...foo) {
    for _, v := range things {
        fmt.Println(v.data)
    }
}

because the type of foo isn't specified.


How can I pass an unspecified number of foos to bar and then access the data field?

CodePudding user response:

One solution seems to be to use reflection and to access the field using FieldByName:

func bar(things ...any) {
    for _, v := range things {
        x := reflect.ValueOf(v)
        fmt.Println(x.FieldByName("data"))
    }
}

It's not clear to me though if this would be considered a cludge and/or dangerous for some reason or other. Presumably, I'd need some checking in there to ensure that everything in things is actually a foo of some variety or I could be trying to access a field that doesn't exist.

  • Related