我想定义一个泛型函数,其中类型约束描述可变结构行为。
我所说的“可变行为”是指这样的接口:
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
方法接收到f
的nil
值时,就会出现这种情况。这一切对我来说都是有意义的,因为var m T
将使指向Foo
的指针的值为零,这是nil。但我不确定我是不是走进了死胡同?
https://go.dev/play/p/H5s59NWNiDA
正如我所能描述的,每当我的类型约束描述一些可变的结构体行为,而我的泛型函数想要初始化,然后改变结构体的示例时,我都会遇到这个问题。这可能吗?有没有更好的方法来解决这个问题?
1条答案
按热度按时间lokaqttq1#
核心问题是为某个类型
T
创建一个有用的值。有几种方法可以做到这一点:m := make(T)
(贴图和通道)等。您可以使用reflect
包来创建值,但让调用者将值作为参数传递会更简单。像这样调用函数:
https://go.dev/play/p/LbSuiXe9zOu