卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章34419本站已运行393

描述可变结构行为的 Go 类型约束

描述可变结构行为的 go 类型约束

php小编新一今天为大家介绍一种描述可变结构行为的 Go 类型约束。在 Go 语言中,我们可以使用接口类型来定义一组方法的集合,并通过类型约束来限制传入参数的类型。这种方式可以在编译时进行类型检查,保证代码的安全性和可靠性。通过合理使用接口类型和类型约束,我们可以实现代码的灵活性和可扩展性,提高程序的可维护性和可读性。接下来,让我们详细了解一下如何使用 Go 类型约束来描述可变结构行为。

问题内容

我想定义一个通用函数,其中类型约束描述可变结构行为。

我所说的“可变行为”是这样的界面:

type Unmarshaler interface {
    Unmarshal(data []byte) error
}

...实现看起来像这样:

type Foo struct {
    Content string
}

func (f *Foo) Unmarshal(data []byte) error {
    f.Content = string(data)
    return nil
}

调用接口方法会改变结构。

我想要做的是定义一个通用函数,其中类型约束是上面的接口。泛型函数负责初始化具体类型的实例,然后使用接口方法对其进行变异并返回。

func Unmarshal[T Unmarshaler](data []byte) (T, error) {
    var m T
    return m, m.Unmarshal(data)
}

所以我希望能够使用 Foo 类型调用该泛型函数。

func main() {
    foo, err := Unmarshal[*Foo]([]byte("hello"))
    if err == nil {
        log.Println(foo.Content) // hello
    } else {
        log.Fatal(err)
    }
}

我必须传递 *Foo 作为类型参数,因为只有指向 Foo 的指针才实现 Unmarshaler 接口。但是,当 Foo 的 Unmarshal 方法收到 fnil 值时,就会出现恐慌。这对我来说都是有意义的,因为 var m T 将使指向 Foo 的指针值为零,即 nil。但我不确定我是否已经走进了死胡同?

https://go.dev/play/p/H5s59NWNiDA

正如我所能描述的那样,每当我的类型约束描述一些可变的结构行为,并且我的泛型函数想要初始化,然后改变结构的实例时,我都会遇到这个问题。这可能吗?有更好的方法来构建这个吗?

解决方法

核心问题是为某些类型 T 创建有用的值。有几种方法可以做到这一点: m := make(T) (地图和频道)等。您可以使用 reflect 包来创建值,但让调用者将值作为参数传递会更简单。

func Unmarshal[T Unmarshaler](m T, data []byte) (T, error) {
    return m, m.Unmarshal(data)
}

像这样调用函数:

foo, err := Unmarshal(&Foo{}, []byte("hello"))

https://www.php.cn/link/8eb51d0a68e9373df41f88e5b551d4a3

卓越飞翔博客
上一篇: 如果第一次匹配条件,如何跳过切片中的值
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏