代码:
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 1
大道至简
|
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
ZSeptember 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 两个类型有两个实例 [![HvvkV0.jpg]( https://s4.ax1x.com/2022/02/21/HvvkV0.jpg)]( 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", } } |