为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
绝地无双 2023-03-15 14:22:39
使用下面给定的类型签名,有没有办法做类似于下面的事情?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 函数?
查看完整描述

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.


查看完整回答
反对 回复 2023-03-15
?
心有法竹

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


查看完整回答
反对 回复 2023-03-15
  • 2 回答
  • 0 关注
  • 150 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号