代码:
type A struct { AID string } type B struct { BID string } type AB interface { A | B } func Get[val AB]() val { return A{ AID: "AID", } }
定义了两个 struct ,A 和 B ,并用定义了一个 constraint 包含了 A ,B 两个 struct ,那么 Get 函数返回 A ,为什么会提示"cannot use (A literal) (value of type A) as val value in return"?
刚刚接触 go 的泛型,还不是特别理解,网上也没搜到相关问题,请教一下大家,这里是哪里的错误?
1 imkerberos 2022-02-21 18:34:32 +08:00 ![]() 大道至简 |
![]() | 2 proxytoworld 2022-02-21 18:45:36 +08:00 楼主代码确定没问题吗,为什么我报错了 |
3 GM 2022-02-21 18:46:25 +08:00 大道至简 /go 头 |
![]() | 4 lesismal 2022-02-21 18:58:12 +08:00 interface 相当于虚基类,配合切面使用基本就能达到其他语言 class 的效果: gist.github.com/lesismal/e2203edd06a17fa5043bbfdbf6cbbaf7 |
![]() | 5 janxin 2022-02-21 19:13:27 +08:00 因为这里泛型不能这么用... 定义 A|B 的时候不是或关系,而是需要 AB 都满足相同约束,你这个地方是不满足的。甚至你把 B 改成 type B struct { AID string BID string } 都是不行的... 原因是 A 不满足 BID 约束 |
![]() | 6 dcalsky 2022-02-21 20:04:42 +08:00 |
7 thevita 2022-02-21 20:10:11 +08:00 @janxin func Show[val AB](v val) { fmt.Println(v) } func main() { a := A{AID: "aid"} b := B{BID: "bid"} Show(a) Show(b) } ---- 约束应该是可以这么用的 还没认真看过 go 的范型,所以不是很了解 大概逻辑是,范型展开的时候,需要根据具体的 代码(及 调用 Get/Show 的代码)中的类型信息( concrete type )进行约束检查,并展开成 concrete type 的代码, 不能用具体返回值来推断 函数返回类型 不然如下代码应该怎么办呢 ---- func FuncA[val AB](yes bool) val { if yes { return A{ AID: "aid" } } else { return B{ BID: "bid" } } } ---- |
![]() | 8 eastphoton 2022-02-21 20:24:12 +08:00 你想用的是多态吧。。。 |
![]() | 9 eastphoton 2022-02-21 20:40:39 +08:00 type A struct { AID string } type B struct { BID string } type AB interface { } func Get() AB { return A{ AID: "AID", } } // ------------------- type AX struct { AID string } type BX struct { AID string } type ABX interface { AX | BX } func GetX[val ABX]() val { return val{ AID: "AID", } } // ------------------- func main() { fmt.Println(Get()) fmt.Println(GetX[AX](), GetX[BX]()) } |
![]() | 10 looplj 2022-02-21 21:04:07 +08:00 union 不支持 struct ,只支持基本类型 |
11 thevita 2022-02-21 21:20:11 +08:00 @ZSeptember 测试了下,应该是支持的,只不过很鸡肋,貌似没啥卵用。 ``` package main import ( "fmt" "runtime" ) type A struct { AID string } type B struct { BID string } type AB interface { A | B } func Show[val AB](v val) { pc := make([]uintptr, 10) // at least 1 entry needed runtime.Callers(0, pc) f := runtime.FuncForPC(pc[0]) fmt.Printf("%s => %x\n", f.Name(), f.Entry()) fmt.Println(v) } func main() { a := A{AID: "aid"} b := B{BID: "bid"} Show(a) Show(b) Show(A{AID: "test"}) } ``` ===== main.Show[...] => 108b0a0 {aid} main.Show[...] => 108b280 {bid} main.Show[...] => 108b0a0 {test} ===== 如上, A, B 两个类型,展开成了两个,Show 函数, 不过 貌似 v val 在 Show 里面什么都做不了,如果要转型成 A 或者 B 需要用 反射,要这范型何用。 请哪位大佬解惑 |
![]() | 12 janxin 2022-02-21 21:33:25 +08:00 |
14 thevita 2022-02-21 21:46:06 +08:00 @janxin 不是的,不是实例化 Stringer 类型 那个 binary 的符号表如下(过滤了下) Show 对 A B 两个类型有两个实例 []( https://imgtu.com/i/HvvkV0) |
![]() | 16 janxin 2022-02-21 22:01:29 +08:00 @thevita 换句话说,对于#6 中的例子中,你使用 fmt.Println(v.AID)是可以编译成功的,但是对顶楼和#7 例子结合的情况,编译是无法通过的。 |
![]() | 17 lysS 2022-02-22 11:19:14 +08:00 go 的泛型还没发布吧,要拉对应分支自己编译 go |
![]() | 18 macscsbf 2022-02-22 13:20:04 +08:00 go 官网提供的泛型教程感觉就不太行 https://taoshu.in/go/generics/design.html?utm_source=wechat_session&utm_medium=social&utm_oi=643495174752309248 不知道这个能不能解决你的问题 |
![]() | 19 cmdOptionKana 2022-02-22 20:12:10 +08:00 刚刚看到一篇文章 《 Go 泛型简明入门教程》,感觉应该这样写:(我没验证) type A struct { AID string } type B struct { BID string } func Get[val A | B]() val { return A{ AID: "AID", } } |