Go中的通用函数

时间:2017-03-10 20:15:30

标签: generics go interface

我正在学习Go,文档和互动课程说空interface可以包含任何类型,因为它不需要额外实现的方法。

举个例子:

func describe(i interace{}) {
    fmt.Printf("Type: %T | Value: %v\n", i, i)
}

...会打印出来......

"Type: int | Value: 5" // for i := 5
"Type: string | Value: test" // for i := "test"
... etc

所以我想我的问题是,这是Go's实现泛型函数的方法,还是有另一种更合适的方法。

3 个答案:

答案 0 :(得分:3)

并不是说您现在就可以在生产中使用泛型(从2020年10月2日开始),但是对于对即将到来的go泛型功能感兴趣的人来说,最新的design draft是go,您可以编写泛型函数{ {1}}如下

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})
}

答案 1 :(得分:2)

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)
    }
}

或者,您可以为知道自己如何串起来的事物定义一个接口(这在基础库中作为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 =("
}

https://play.golang.org/p/Ez6Hez6cAv

这使您可以使用类似通用的功能,但仍保留类型安全性,并且行为本身由类型定义,而不是通用函数。

Go鼓励您以这种方式考虑类型,基于他们的行为,他们可以做什么而不是他们包含

答案 2 :(得分:1)

Golang没有通用类型,所以你解决这个问题的方法是传递interface类型并在函数中使用类型开关。