Created
September 14, 2023 04:29
-
-
Save mfirhas/19d37da0f2eaa55eaaa5f7901d756cbe to your computer and use it in GitHub Desktop.
Just small experiment and poc with Go's generics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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