m_c*_*ens 7 generics interface go
我正在学习Go
,文档和互动课程说空interface
可以容纳任何类型,因为它不需要额外实现的方法。
举个例子:
func describe(i interface{}) {
fmt.Printf("Type: %T | Value: %v\n", i, i)
}
Run Code Online (Sandbox Code Playgroud)
......会打印出来......
"Type: int | Value: 5" // for i := 5
"Type: string | Value: test" // for i := "test"
... etc
Run Code Online (Sandbox Code Playgroud)
所以我想我的问题是这是否Go's
是实现通用功能的方式,或者是否有另一种更合适的方式来实现它们。
Kae*_*dys 11
Go 范式通常通过在非空接口中实现行为来避免这种情况。例如,假设您想打印具有特定类型格式的内容:
func Print(i interface{}) {
switch o := i.(type) {
case int64:
fmt.Printf("%5d\n", o)
case float64:
fmt.Printf("%7.3f\n", o)
case string:
fmt.Printf("%s\n", o)
default: // covers structs and such
fmt.Printf("%+v\n", o)
}
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以为知道如何将自己串起来的东西定义一个接口(它作为 存在于基础库中fmt.Stringer
),并使用它:
type Stringer interface {
String() string
}
func Print(o Stringer) {
fmt.Println(o.String())
}
type Foo struct {
a, b int
}
func (f Foo) String() string {
// Let's use a custom output format that differs from %+v
return fmt.Sprintf("%d(%d)", f.a, f.b)
}
type Bar struct {
t bool
}
func (b Bar) String() string {
if b.t {
return "TRUE! =D"
}
return "false =("
}
Run Code Online (Sandbox Code Playgroud)
https://play.golang.org/p/Ez6Hez6cAv
这让您拥有类似泛型的功能,但仍保留类型安全性,并且行为本身由 types定义,而不是您的泛型函数。
Go 鼓励你以这种方式思考类型,基于它们的行为,它们可以做什么,而不是它们包含的内容。
截至 2021 年 6 月,泛型无法用于生产,但对于对即将推出的 go 泛型功能感兴趣的人,使用 go 的设计提案(预计在 2022 年初可用),您可以编写Print
如下泛型函数
package main
import (
"fmt"
)
// T can be any type. Compilation will fail if T is not iterable.
func Print[T any](s []T) {
for _, v := range s {
fmt.Print(v)
}
}
func main() {
// Passing list of string works
Print([]string{"Hello, ", "world\n"})
// You can pass a list of int to the same function as well
Print([]int{1, 2})
}
Run Code Online (Sandbox Code Playgroud)
输出:
Hello, world
12
Run Code Online (Sandbox Code Playgroud)