2 回答

TA贡献1862条经验 获得超6个赞
您可以使您的代码片段工作:
func Transform[T, U any](item T) U {
return any(item).(U)
}
但是如果与 的实际类型不断言兼容,代码将因恐慌而失败:Uitem
这会恐慌:
fmt.Println(Transform[string, int]("foo"))
// Output: panic: interface conversion: interface {} is string, not int
这在没有恐慌的情况下成功了,因为bytes.Buffer它同时实现了io.Reader和io.Writer接口:
b := &bytes.Buffer{}
_ = Transform[io.Writer, io.Reader](b)
所以,可以做你想做的事。但我不确定它有多大用处,因为实际参数运行时失败与U.

TA贡献1866条经验 获得超5个赞
T如果您的函数定义为 return ,则无法返回U。即使您断言Tto U,该函数仍会返回U。
如果你真的想返回or T,U你需要将返回类型声明为any:
func (s SomeStruct[T, U]) Transform(elem T) any { /* ... */ }
...放弃静态类型;或者您可以使用“任一”类型的助手:
type Either[T, U any] struct {
value any
}
// Either methods
func (s SomeStruct[T, U]) Transform(elem T) Either[T, U] {
if s.transform == nil {
return Either[T, U]{elem}
}
return Either[T, U]{s.transform(elem)}
}
看看如何在这个 playground中使用它。
备选方案将偏离您的既定目标。一种是实际断言Tto U,但您必须知道这会返回U,而不是T,即使T它的值可分配给U:
func (s SomeStruct[T, U]) Transform(elem T) U {
if s.transform == nil {
if u, ok := any(elem).(U); ok {
return u
}
return *new(U) // U's zero value if elem assertion fails
}
return s.transform(elem)
}
您必须使用断言,因为类型参数T和U都受 约束any,因此(理所当然地)没有其他方式来表达两者之间的可转换性。comma-ok 习惯用法有助于避免运行时恐慌。
或者您可以返回(U, error),这通常是合理的做法:
func (s SomeStruct[T, U]) Transform(elem T) (u U, err error) {
if s.transform == nil {
err = errors.New("transform function not set")
return
}
u = s.transform(elem)
return
}
游乐场:https://go.dev/play/p/GKLRmKKWxlP
- 2 回答
- 0 关注
- 150 浏览
添加回答
举报