marp | theme | paginate | style |
---|---|---|---|
true |
default |
true |
section h1 {
font-size: 2em;
text-align: center;
}
section h2 {
position: absolute;
top: 1.2em;
left: 0;
right: 0;
font-size: 1.5em;
text-align: center;
}
section h3 {
font-size: 1.2em;
}
section h4 {
font-size: 1em;
}
section p {
font-size: 1em;
text-align: center;
}
section li {
font-size: 1em;
}
section.left p {
text-align: left;
}
|
by Jin
- Overloading
- Coercion
- Inclusion
- Parametric (Generics)
By Christopher Strachey, Luca Cardelli, Peter Wegner.
mkdir generics
cd generics
docker run --rm -it \
-v $PWD:/go/src/generics \
-w /go/src/generics golang:1.18beta1-buster bash
go mod init example/generics
touch main.go
func Foo[T any, ...](parameters...) ReturnType
- T:类型名
- any:约束
func SumInteger[T constraints.Integer](a, b T) T {
return a + b
}
sum := SumInteger[int](1, 2)
type Vector[T any] struct {
inner []T
}
func (m *Vector[T]) Len() int {
return len(m.inner)
}
func (m *Vector[T]) Get(index int) T {
return m.inner[index]
}
type Array[T any] [8]T
type Slice[T any] []T
type Map[K comparable, V any] map[K]V
type Chan[T] chan T
type Iterator[T any] interface {
Next() bool
Value() T
}
type ListIter[T any] struct {
index int
inner []T
}
func (m *ListIter[T]) Next() (bool) {
...
}
func (m *ListIter[T]) Value() T {
...
}
type Fn[A any, B any] func(A) B
type MyInt[T fmt.Stringer] int
...
- any 相当于 interface{}
- comparable 可以使用 == 和 != 操作符
type Stringer interface {
String() string
}
type Integer interface {
int64
}
type Integer interface {
~int64
}
type Integer interface {
int | int8 | int16 | int32 | int64
}
type Integer interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}
type StringerInteger interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
String() string
}
- 非接口类型 T :
{int}, {float32}, {string} ...
- 空接口 interface {} 或 any :
所有类型
- interface { f1(); f2(); f3() ... }:
{t : t declared {f1, f2, f3 ...}}(简写为 {t: decl(t, Sfs)} )
- interface { M; N }( interface M {...}, interface N {...} ):
SM ∩ SN
- interface { ~T }:
{t : t ~ T}(底层类型为 T 的类型)
- interface { X | Y | Z }:
SX ∪ SY ∪ SZ
- interface { M; X | Y | Z; f1(); f2(); f3() ...}:
SM ∩ (SX ∪ SY ∪ SZ) ∩ { t : decl(t, Sfs)}
- interface { int; string }:
{int} ∩ {string} = ∅
// SOrdered: {t : t ~ int} ∪ {t : t ~ int8} ∪ {t : t ~ int16} ∪ ...
type Ordered interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~string
}
func Max[T Ordered](a, b T) T {
if a > b {
return a
}
return b
}
func main() {
// {int} ⊆ SOrdered.
Max[int](1, 2)
// {string} ⊆ SOrdered.
Max[string]("a", "b")
// INVALID: []byte ⊄ SOrdered.
Max[[]byte]([]byte("hello"))
}
// T 关联的类型集合为所有实现了 fmt.Stringer 接口的类型
func JoinSlice[T fmt.Stringer](elements []T, seperator string) string {
var ret string
for i, v := range elements {
ret += v.String() // 类型T的对象可以使用其方法
if i < len(elements) - 1 {
ret += seperator
}
}
}
// T 关联的类型集合为所有可比较的类型
func SearchIndex[T comparable](elements []T, target T) int {
index := -1
for i, e := range elements {
if e == target { // 类型T的对象可以使用“==”比较
index = i
break
}
}
return index
}
// 有序类型,下面构成Ordered的的所有类型都是可以比较大小的
type Ordered interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~string
}
// T 关联的类型集合为 Ordered 对应的类型集合
func Max[T Ordered](a, b T) T {
if a >= b { // 可以比较大小
return a
}
return b
}
// 自定义泛型Slice约束
type MySlice[T any] interface {
[]T
}
func ForEachMySlice[T any, S MySlice[T]](s S) {
for _, e := range s {
fmt.Println(e)
}
}
// 自定义泛型Map约束
type MyMap[K comparable, V any] interface {
map[K]V
}
func ForEachMyMap[K comparable, V any, M MyMap[K, V]](m M) {
for k, v := range m {
fmt.Println(k, v)
}
}
// 自定义泛型Channel约束
type MyChan[T any] interface {
chan T
}
func ForEachChan[T any, C MyChan[T]](c C) {
for v := range c {
fmt.Println(v)
}
}
标准库提供的约束constraints
type Signed interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}
type Unsigned interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}
type Integer interface {
Signed | Unsigned
}
...
- 指定类型参数
sum := SumInteger[int](1, 2)
- 推断类型参数
sumVal := SumInteger(1, 2, 3)
类型参数 T1、T2,[]map[int]bool 可与以下类型合一化:
- []map[int]bool
- T1 (T1 -> []map[int]bool)
- []T1 (T1 -> map[int]bool)
- []map[T1]T2 (T1 -> int, T2 -> bool)
func Map[F, T any](s []F, f func(F) T) []T {
r := make([]T, len(s))
for i, v := range s {
r[i] = f(v)
}
return r
}
// []int : []F, { F -> int }.
// func(i int) string : func(F) T, { F -> int,T -> string }.
// Map[int, string](...).
strs := Map([]int{1, 2, 3}, strconv.Itoa)
func NewPair[F any](f1, f2 F) *Pair[F] { ... }
// int : F, { F -> int }.
// NewPair[int](...).
NewPair(1, 2)
// untyped int : F, { F -> ? }.
// int64 : F, { F -> int64 }.
// NewPair[int64](...).
NewPair(1, int64(2))
[T Constraint1[V], V Constraint2],对于 T 可进行类型推断仅当:
- Constraint1 对应的类型集合中只包含一个非接口类型;
- Constraint1 对应的类型集合中的所有类型的底层类型相同;
type SC[E any] interface {
[]E
}
func DoubleDefined[S SC[E], E constraints.Number](s S) S {
r := make(S, len(s))
for i, v := range s {
r[i] = v + v
}
return r
}
func main() {
v := DoubleDefined([]int{1})
// ...
}
如果可以进行约束类型推断,那么函数的类型推断步骤如下:
- 使用已知的类型参数构建映射关系;
- 进行约束类型推断;
- 使用有类型的实参进行函数类型推断;
- 再次进行约束类型推断;
- 针对剩余的无类型实参使用默认类型进行函数类型推断;
- 再次进行约束类型推断;
type Equaler interface {
Equal(Equaler) bool
}
func Index[T Equaler](s []T, e T) int {
for i, v := range s {
if e.Equal(v) {
return i
}
}
return -1
}
func Index[T interface { Equal(T) bool }](s []T, e T) int {
for i, v := range s {
if e.Equal(v) {
return i
}
}
return -1
}
type StringableSignedInteger interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
String() string
}
type MyInt int
func (mi MyInt) String() string {
return fmt.Sprintf("MyInt(%d)", mi)
}
// type set: Ø
type StringableSignedInteger2 interface {
int | int8 | int16 | int32 | int64
String() string
}
type Setter interface {
Set(string)
}
func FromStrings[T Setter](s []string) []T {
result := make([]T, len(s))
for i, v := range s {
result[i].Set(v)
}
return result
}
type Settable int
func (p *Settable) Set(s string) {
i, _ := strconv.Atoi(s)
*p = Settable(i)
}
func F() {
// INVALID
nums := FromStrings[Settable]([]string{"1", "2"})
...
}
type Setter[B any] interface {
Set(string)
*B // 非接口类型元素
}
func FromStrings[T any, PT Setter[T]](s []string) []T {
result := make([]T, len(s))
for i, v := range s {
p := PT(&result[i])
p.Set(v)
}
return result
}
type Integer interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}
type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | float32 | float64
}
func Convert[To Integer, From Number](from From) To {
to := To(from)
if From(to) != from {
panic("conversion out of range")
}
return to
}
fmt.Println(reflect.TypeOf(List[int]{1}))
// 运行输出 List[int]
func ZeroVal[T any]() T {
var zero T
return zero
}
type Float interface {
~float32 | ~float64
}
func NewtonSqrt[T Float](v T) T {
var iterations int
switch (interface{})(v).(type) {
case float32:
iterations = 4
case float64:
iterations = 5
default:
panic(fmt.Sprintf("unexpected type %T", v))
}
// Code omitted.
}
type MyFloat float32
NewtonSqrt(MyFloat(64)) // panic
type S struct{}
func (S) Identity[T any](v T) T { return v }
- 泛型类型特化
- 基于泛型的元编程
- 高级抽象
- 协变和逆变
- 柯里化
- 可变类型参数
- 参数化非类型值