在恒等函数中将类型 T 转换为类型 U

使用下面给定的类型签名,有没有办法做类似于下面的事情?


func Transform[T, U any](item T) U {

    return item

}

上面的代码给出了以下错误:


cannot use item (variable of type T constrained by any) as U value in return 

statement

我无法使用上面的类型签名,因为我本质上是在尝试制作一个可选的转换方法,有时需要从 T 转换为 U,但有时只返回自身。下面显示了一个更详细的用例示例。


type SomeStruct[T, U any] struct {

    Transform func(T) U

}


func (s SomeStruct[T, U]) Transform(elem T) (U) {

    if s.Transform != nil {

        return s.Transform(elem)

    }

    return elem

}

有没有办法创建一个有时有条件地只返回自身的 Transform 函数?


绝地无双
浏览 151回答 2
2回答

阿波罗的战车

您可以使您的代码片段工作: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.

心有法竹

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 methodsfunc (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
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go