编辑
2024-09-11
Know Go Generics
00
请注意,本文编写于 71 天前,最后修改于 71 天前,其中某些信息可能已经过时。

目录

类型定义
Slices
Go 中没有泛型类型
使用 interface 实例化泛型类型
Maps
多类型参数
Structs
Methods
零值
方法上的类型参数
Interfaces
Channels

一些使用泛型类型的例子。

类型定义

对现有类型重新定义是允许的,这么做可以对类型重新起一个意思明确的名字,并且可以在其上定义方法:

go
type MyInt int type Port int

但是对[T any]重新定义是不允许的,从设计上来说,对任意类型重新起名字没什么用。

go
type MyT[T any] T // ^ // cannot use a type parameter as RHS in type declaration

Slices

go
type Bunch[E any] []E // 在使用时实例化 b := Bunch[int]{1, 2, 3}

Go 中没有泛型类型

在代码中所定义的泛型类型,在编译时都会实例化为具体类型。

使用 interface 实例化泛型类型

go
type Bunch[E any] []E var b Bunch[error] b = append(b, errors.New("oh no")) fmt.Println(b) // [oh no]

Maps

go
type Catalog[V any] map[string]V cat := Catalog[int]{} fmt.Println(cat["bogus"]) // 0

多类型参数

go
// 对于 map 来说,key 必须是 comparable 的 type Index[K comparable, V any] map[K]V age := Index[string, int]{} age["John"] = 29 fmt.Println(age["John"]) // 29

Structs

go
type NamedThing[T any] struct { Name string Thing T } n := NamedThing[float64]{ Name: "Latitude", Thing: 50.406, } fmt.Println(n) // {Latitude 50.406} // 嵌套泛型类型 p := NamedThing[NamedThing[float64]]{ Name: "Position", Thing: NamedThing[float64]{ Name: "Latitude", Thing: 50.406, }, } fmt.Println(p) // {Position {Latitude 50.406}}

Methods

go
type Bunch[E any] []E // 方法的 receiver 上不用写约束 func (b Bunch[E]) First() E { return b[0] } b := Bunch[string]{"a", "b", "c"} fmt.Println(b.First()) // a

零值

go
func (b Bunch[E]) First() E { var zero E if len(b) == 0 { return zero } return b[0] }

方法上的类型参数

不允许这种定义:

go
func (b Bunch[E]) PrintWith[T any](v T) { fmt.Println(v, b) } // methods cannot have type parameters

Interfaces

go
type Equaler[T any] interface { Equal(T) bool }

Channels

go
type myChan[E any] chan E ch := make(myChan[error]) go func() { ch <- errors.New("oh no") }() fmt.Println(<-ch) // oh no

本文作者:jdxj

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!