Skip to content

Instantly share code, notes, and snippets.

@mfirhas
Created September 14, 2023 04:29
Show Gist options
  • Save mfirhas/19d37da0f2eaa55eaaa5f7901d756cbe to your computer and use it in GitHub Desktop.
Save mfirhas/19d37da0f2eaa55eaaa5f7901d756cbe to your computer and use it in GitHub Desktop.
Just small experiment and poc with Go's generics
// go version go1.21.1 darwin/amd64
// $ go build -gcflags="-m -m"
package main
func main() {
// p escapes to heap
// because Func has generic parameter with type constraint containing method(s)
// gcshape of pointer argument to type parameter is not monomorphized, hence need to create vtable to contains methods.
p := &Pointer{}
Func(p)
// p doesn't escape to heap
// because Fn has interface parameter
// compiler can de-virtualized the call if we're not passing around data from methods calls.
// this is cheaper than generic version above since it has no vtable to contain methods of interfaces, unlike the generic version
pp := &Pointer{}
Fn(pp)
d := Data{}
// d doesn't escape since we are not passing pointer to generic param, so generics will be monomorphized.
GetData(d)
GetDataBased(d)
dp := &Data{}
// call to this function will cause dp escapes to heap because we are passing pointer and type constraint contains method(s)
// if we are not providing type constraint with method(s), d won't escape
GetData(dp)
// dp won't escape since this method's generic param type constraint has no method(s), just "union".
// but, since we are declaring `GetData(dp)` makes dp escape, and function calls order doesn't matter.
GetDataBased(dp)
}
type Pointer struct{}
type Interface interface {
Method()
}
type Data struct {
Number int
}
func GetData[T Union](t T) {
t.Method()
}
func GetDataBased[T UnionBased](t T) {
}
type Union interface {
int | string | Data | *Data
Method()
}
func (d Data) Method() {
}
// func (d *Data) Method() {
// }
type UnionBased interface {
~int | ~string | Data | *Data
}
func (p *Pointer) Method() {
}
func Func[T Interface](t T) {
t.Method()
}
func Fn(t Interface) {
t.Method()
}
// // cannot declare multiple type constraints
// func MultipleBounds[T Interface + Union](t T) {
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment