Go 泛型中什么时候不需要波浪号?

Der*_*rek 1 generics go

在 Golang 的新泛型中,我们有波浪号运算符 ~ ,它将匹配底层类型。在什么情况下不匹配底层类型是有效的?我试图理解为什么当前的波浪号行为不是默认行为。似乎没有必要两者都支持。

例如,你为什么要写

interface { int }
Run Code Online (Sandbox Code Playgroud)

并不是

interface { ~int }
Run Code Online (Sandbox Code Playgroud)

编写一个如此严格以至于不能接受类似内容的方法对您有什么好处

type MyInt int
Run Code Online (Sandbox Code Playgroud)

为什么波形符行为不是默认行为,因此该语言不需要另一个运算符?

icz*_*cza 6

不使用~运算符意味着您只接受列出的确切类型。为什么这很重要?

您可能希望使用确切类型的值来设置其他变量,否则需要进行类型转换。又因为俗话说“新类型,新方法集”。具有相同基础类型的新类型有自己的方法集

您可能想要该值的“原始”行为,如果它设置了不同的方法,则该行为可能会发生变化。

例如,假设您想像这样打印数字:

type Num interface{ ~int }

func foo[T Num](v T) {
    fmt.Println(v)
}
Run Code Online (Sandbox Code Playgroud)

如果MyInt有一个String() string方法:

type MyInt int

func (m MyInt) String() string { return "bar" }
Run Code Online (Sandbox Code Playgroud)

输出可能不是foo()想要的,因为fmt包检查打印值是否有String() string方法,如果有,则调用它来获取其string表示形式:

foo(1)
foo(MyInt(1))
Run Code Online (Sandbox Code Playgroud)

这将输出(在Go Playground上尝试):

1
bar
Run Code Online (Sandbox Code Playgroud)

如果您只允许int

type Num interface{ int }
Run Code Online (Sandbox Code Playgroud)

您仍然可以使用类型转换foo()来调用 type 的值:MyInt

foo(1)
x := MyInt(1)
foo(int(x))
Run Code Online (Sandbox Code Playgroud)

输出将是foo()想要的,而不是想要的(在Go PlaygroundMyInt上尝试这个):

1
1
Run Code Online (Sandbox Code Playgroud)

foo()是的,如果它本身会进行转换,这也是可能的,但这清楚地记录了您想要一个纯粹的int, withint的行为,而不是具有int不同的自定义行为的东西。