Is there a difference between Environment
and Environment_g
in the following example?
package main
import "fmt"
type Variable[A any] interface {
Get() A
Set(A) error
}
type Environment map[string]Variable[any]
type Environment_g[V Variable[any]] map[string]V
func main() {
e := new(Environment)
eg := e
fmt.Println(e, eg)
}
Or are this just two ways to do the same?
There is no difference in the sense that given a type that implements the interface Variable[any]
, you can assign it to the values of both maps:
type Foo struct {
v any
}
func (f Foo) Get() any {
return f.v
}
func (f Foo) Set(v any) error {
f.v = v
return nil
}
You can assign it to both maps:
func main() {
e := Environment{}
g := Environment_g[Foo]{}
e["key"] = Foo{1}
g["key"] = Foo{2}
}
The second definition just adds a layer of abstraction (obfuscation?).
The most glaring difference is:
map[string]Variable[any]
you can assign Foo
s to the key entries but also any other struct that implements Variable[any]
.Environment_g[Foo]
is equivalent to map[string]Foo
, which will hold only values of type Foo
.This is the same as map[string]any
vs. map[string]int32
: the former can hold int32
values among others, whereas the latter obviously can't.
Another closely related reading is: Difference between any/interface{} as constraint vs. type of argument?
Other than that, they are not the same type, just like map[string]any
and map[string]int32
are not, with all the usual implications: you can't convert one type to the other, can't assign one type to the other, etc.
Again, when thinking about this consider what the generic type is equivalent to after instantiation. It eventually boils down to map[string]someInterface
and map[string]concreteType
.
The only case where the maps would be almost equivalent is when you instantiate the type parameter with the same value type of the non-generic map. But the types still have different names, so a conversion is required.
a := Environment{} // it's a map[string]Variable[any]
b := Environment_g[Variable[any]] // it's also a map[string]Variable[any]
a = Environment(b) // ok, with type conversion
This answer ignores the red herring of instantiating a type parameter with any
. For that see this