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

问题描述 投票:0回答:1

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

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

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
方法收到
nil
f
值时,就会出现恐慌。这对我来说都是有意义的,因为
var m T
将使指向
Foo
的指针值为零,即 nil。但我不确定我是否已经走进了死胡同?

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

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

go pointers generics types initialization
1个回答
0
投票
将值传递给解组函数:

func Unmarshal[T Unmarshaler](m T, data []byte) (T, error) { return m, m.Unmarshal(data) }
这样称呼:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.