Go: 泛型中`~`的用法

在Go语言的泛型中,~​ 符号用于类型约束中的类型推断。它允许你指定一个基础类型,并且约束类型参数必须是该基础类型或其别名。

基础类型约束

在Go泛型中,类型约束可以使用 ~​ 符号来表示基础类型。例如,如果你想要约束一个类型参数必须是 int​ 或者是 int​ 的别名类型,可以这样定义:

go 复制代码
package main

import "fmt"

// 定义一个别名类型
type MyInt int

// 定义一个泛型函数,T 必须是 int 或 int 的别名类型
func PrintNumber[T ~int](n T) {
    fmt.Println(n)
}

func main() {
    var a int = 10
    var b MyInt = 20

    PrintNumber(a) // 输出: 10
    PrintNumber(b) // 输出: 20
}

在这个例子中,PrintNumber​ 函数使用了 ~int​ 作为类型约束,这意味着类型参数 T​ 可以是 int​ 或者是 int​ 的别名类型 MyInt​。

结合类型约束

你可以将 ~​ 符号与其他类型约束结合使用,以创建更复杂的约束。例如,约束一个类型参数必须是 int​ 或 float64​ 的基础类型或其别名:

go 复制代码
package main

import (
    "fmt"
    "golang.org/x/exp/constraints"
)

// 定义一个别名类型
type MyFloat float64

// 定义一个泛型函数,T 必须是 int 或 float64 的基础类型或其别名
func PrintNumber[T ~int | ~float64](n T) {
    fmt.Println(n)
}

func main() {
    var a int = 10
    var b MyFloat = 20.5

    PrintNumber(a) // 输出: 10
    PrintNumber(b) // 输出: 20.5
}

在这个例子中,PrintNumber​ 函数使用了 ~int | ~float64​ 作为类型约束,这意味着类型参数 T​ 可以是 int​ 或 float64​ 的基础类型或其别名类型 MyFloat​。

使用 constraints​ 包

Go 1.18 引入了 constraints​ 包,其中包含一些常用的类型约束。你可以结合 ~​ 符号使用这些约束。例如,约束一个类型参数必须是有序类型的基础类型或其别名:

go 复制代码
package main

import (
    "fmt"
    "golang.org/x/exp/constraints"
)

// 定义一个别名类型
type MyString string

// 定义一个泛型函数,T 必须是有序类型的基础类型或其别名
func Min[T ~constraints.Ordered](a, b T) T {
    if a < b {
        return a
    }
    return b
}

func main() {
    var a string = "apple"
    var b MyString = "banana"

    fmt.Println(Min(a, b)) // 输出: apple
}

在这个例子中,Min​ 函数使用了 ~constraints.Ordered​ 作为类型约束,这意味着类型参数 T​ 可以是有序类型的基础类型或其别名类型 MyString​。