'Generic Structs with Go

What is the equivalent of this C# code in Go, how can I build it

    class ModelX<T>
    {
        public T Data { get; set; }
    }

    ModelX<int>

I have tried something like:

    type ModelX<T> struct {
        ModelY
        Data []T
    }

    m := ModelX<T>

How to do this? Is that possible?



Solution 1:[1]

Starting with Go 1.18, you can define generic types:

type Model[T any] struct {
    Data []T
}

A generic type must be instantiated1 when used, and instantiation requires a type parameter list:

func main() {
    // passing int as type parameter
    modelInt := Model[int]{Data: []int{1, 2, 3}}
    fmt.Println(modelInt.Data) // [1 2 3]

    // passing string as type parameter
    modelStr := Model[string]{Data: []string{"a", "b", "c"}}
    fmt.Println(modelStr.Data) // [a b c]
}

More info and common gotchas about instantiations: Go error: cannot use generic type without instantiation

If you declare methods on a generic type, you must repeat the type parameter declaration on the receiver, even if the type parameters are not used in the method scope — in which case you may use the blank identifier _ to make it obvious:

func (m *Model[T]) Push(item T) {
    m.Data = append(m.Data, item)
}

// not using the type param in this method
func (m *Model[_]) String() string {
    return fmt.Sprint(m.Data)
}

An important detail is that — unlike functions2 —, generic types must always supply all3 type parameters upon instantiation. For example, this type:

type Foo[T any, P *T] struct {
    val T
    ptr P
}

must be instantiated with both types, even if some of them could be inferred:

func main() {
    v := int64(20)
    foo := Foo[int64, *int64]{val:v, ptr: &v}

    fmt.Println(foo)
}

Playground: https://go.dev/play/p/n2G6l6ozacj


Footnotes:

1: Language specs about instantiations: https://golang.org/ref/spec#Instantiations

2: The quote from the specs is "Calls to parameterized functions may provide a (possibly partial) type argument list, or may omit it entirely if the omitted type arguments are inferrable from the ordinary (non-type) function arguments.". This quote excludes parametrized types

3: in early beta releases, the type param list in generic types could be partial; this feature has been disabled.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1