Go 中的通用函数

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 鼓励你以这种方式思考类型,基于它们的行为,它们可以做什么,而不是它们包含的内容


May*_*tel 9

截至 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)