Golang泛型 - 是否有类似Rust中"Self"类型的等价实现
Golang泛型 - 是否有类似Rust中"Self"类型的等价实现 Rust 泛型有一个“Self”,它是实例化泛型类型的具体类型。Go 中有等效的概念吗?
具体来说,这样我就可以让 Clone() 返回一个 Self。然后我可以有一个实现 Clone 接口的泛型结构体。
类似这样:
type Cloner[T any] interface {
Clone() T
}
type Parent[T any] struct {
parentAttr T
Cloner[Self]
}
func (p Parent[T]) Clone() Parent[T] { return a clone of the parent obj }
type Child[T any] struct {
Parent[T]
childAttr string
}
func (c Child[T]) Clone() Child[T] { return a clone of the child obj }
更多关于Golang泛型 - 是否有类似Rust中"Self"类型的等价实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html
嗨 @guettli,
为什么不用
cloned := s.Clone()并让每个 Clone 方法返回特定的类型?
因为那样 Clone 方法将不会实现 Cloner 接口。
如果你的场景不需要 Cloner 接口,你的解决方案当然完全没问题。始终使用尽可能简单的解决方案!
嗨,克里斯托夫,
感谢你的博客文章。
你在文章中使用了这段代码片段:
cloned := CloneAny(s)
if cs, ok := cloned.(CloneableSlice); ok {
fmt.Println(cs[3])
}
为什么不使用 cloned := s.Clone() 并让每个 Clone 方法都返回特定的类型呢?
这样你就不需要类型断言了。
你好,
确实,接口方法的参数可以引用接口类型本身——详情请参阅这篇文章:
简要说明:
第一步:Cloner 接口保持不变。
type Cloner[C any] interface {
Clone() C
}
C 目前还没有任何限制,但第二步会处理这个问题。
第二步:一个克隆任意类型的函数使用 Cloner[T] 作为类型约束:
func CloneAny[T Cloner[T]](c T) T {
return c.Clone()
}
然后,对于任何其类型实现了 Cloner 的变量 s,你都可以简单地调用
CloneAny(s)
来克隆 s。
这篇博客文章更详细地解释了这个解决方案。
在Go语言中,没有与Rust的Self类型完全等价的实现。Go的泛型系统相对较新,设计上更注重简单性和明确性,因此不支持这种形式的自我类型引用。
不过,你可以通过以下方式实现类似的功能:
package main
import "fmt"
// 定义一个泛型克隆接口
type Cloner[T any] interface {
Clone() T
}
// 父结构体
type Parent[T any] struct {
parentAttr T
}
// 父结构体的Clone方法
func (p Parent[T]) Clone() Parent[T] {
return Parent[T]{parentAttr: p.parentAttr}
}
// 子结构体
type Child[T any] struct {
Parent[T]
childAttr string
}
// 子结构体的Clone方法
func (c Child[T]) Clone() Child[T] {
return Child[T]{
Parent: c.Parent.Clone(),
childAttr: c.childAttr,
}
}
// 使用接口约束的泛型函数
func CloneAndPrint[T Cloner[T]](original T) {
cloned := original.Clone()
fmt.Printf("Original: %+v\n", original)
fmt.Printf("Cloned: %+v\n", cloned)
}
func main() {
// 创建Parent实例
parent := Parent[int]{parentAttr: 42}
clonedParent := parent.Clone()
fmt.Printf("Parent cloned: %+v\n", clonedParent)
// 创建Child实例
child := Child[string]{
Parent: Parent[string]{parentAttr: "parent value"},
childAttr: "child value",
}
clonedChild := child.Clone()
fmt.Printf("Child cloned: %+v\n", clonedChild)
// 使用泛型函数
CloneAndPrint(parent)
CloneAndPrint(child)
}
另一种方法是使用类型参数约束:
package main
import "fmt"
// 定义可克隆的接口
type Cloneable interface {
Clone() Cloneable
}
// 具体实现
type MyStruct struct {
Value int
}
func (m MyStruct) Clone() Cloneable {
return MyStruct{Value: m.Value}
}
// 泛型包装器
type Container[T Cloneable] struct {
item T
}
func (c Container[T]) CloneContainer() Container[T] {
return Container[T]{item: c.item.Clone().(T)}
}
func main() {
original := Container[MyStruct]{item: MyStruct{Value: 100}}
cloned := original.CloneContainer()
fmt.Printf("Original: %+v\n", original)
fmt.Printf("Cloned: %+v\n", cloned)
}
需要注意的是,Go的泛型设计哲学与Rust不同。Go更倾向于通过接口和明确的类型转换来实现多态,而不是通过复杂的类型系统特性。虽然不能完全复制Rust的Self行为,但通过上述模式可以在Go中实现类似的功能。

