In the following code I have a token type that contains a literal value. By using an empty interface I can create a slice of tokens and append tokens that have different types. I don't think it's possible to accomplish the same using generics since we wouldn't be able to infer a type for the Slice of tokens. Is this assumption correct?
type Token struct {
TokenType string
Literal interface{}
}
func main(){
tok1 := &Token{TokenType: "string", Literal: "foo"}
tok2 := &Token{TokenType: "integer", Literal: 10}
tokS := []*Token{tok1, tok2}
}
CodePudding user response:
Is this assumption correct?
Yes. Your can have a slice of Token[string] or Token[int].
CodePudding user response:
since we wouldn't be able to infer a type for the Slice of tokens. Is this assumption correct?
Almost. More precisely, the slice of Token
wouldn't infer anything because you yourself must construct it with a concrete instantiation of the generic type.
Given a parametrized Token
type as:
type Token[T any] struct {
TokenType string
Literal T
}
each instantiation with a different type parameter produces a different (named) type.
So when you construct a slice with a specific instance of Token[T any]
, different instances are simply not assignable to its element type:
tokS := []*Token[string]{tok1, tok2}
// invalid: cannot use tok2 (variable of type *Token[int]) as type *Token[string] in array or slice literal
The only slice that can hold different types, as Token[string]
and Token[int]
is []interface{}
or []any
.
A further note, type inference is used to deduce missing type parameters from those already supplied, or in case of functions, from function arguments. Generic types must be instantiated with a non-empty type parameter list. When the type param is only one, like Token[T any]
, you must provide that explicitly and there's nothing left to infer.