我實作了一個基于泛型的 Set,一切正常,直到我使用 struct 作為 Set 元素而不是基本型別。我得到一個編譯錯誤。
去版本:go version go1.18 windows/amd64
下面的代碼未能符合功能AddSet。
package main
import (
"fmt"
"golang.org/x/exp/maps"
)
type Key struct {
A, B int
}
func main() {
s := SetOf(
Key{1, 1},
Key{2, 2},
Key{3, 3},
)
s.AddSet(SetOf(
Key{3, 3},
Key{4, 4},
Key{5, 5},
))
fmt.Println(s)
}
type Set[T comparable] map[T]struct{}
func SetOf[T comparable](vs ...T) Set[T] {
s := Set[T]{}
for _, v := range vs {
s[v] = struct{}{}
}
return s
}
func (s Set[T]) AddSet(another Set[T]) {
maps.Copy(s, another)
}
運行時:
> go run .\main.go
# command-line-arguments
.\main.go:19:10: cannot use &.autotmp_29 (type *struct { A int; B int }) as type *Key in argument to runtime.mapassign
<autogenerated>:1: cannot use &.autotmp_12 (type *struct { A int; B int }) as type *Key in argument to runtime.mapassign
- 如果
Key只有 1 個欄位,則可以編譯成功。 - 如果我使用
for v := range another { s[v]=struct{}{} },它可以編譯成功。
我覺得這很奇怪,有人可以解釋一下嗎?
uj5u.com熱心網友回復:
看起來像這個編譯器錯誤。很可能它將在 Go 1.19 中修復并向后移植到 Go 1.18.1 1.18.2。
現在,我建議您放棄maps包裝并手動操作,就像您已經嘗試過的那樣。這只是一個簡單的回圈:
func (s Set[T]) AddSet(another Set[T]) {
for k := range another {
s[k] = struct{}{}
}
}
@icza 將命名映射型別顯式轉換為其基礎型別的注釋也有效:
maps.Copy(map[T]struct{}(s), another)
如果您使用需要多個映射型別引數(具有相同約束)的函式,如maps.Equalor maps.EqualFunc,則必須轉換兩個引數:
func (s Set[T]) Compare(another Set[T]) bool {
// signature is Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool
return maps.Equal(map[T]struct{}(s), map[T]struct{}(another))
}
似乎使用 len >= 2 的陣列實體化的引數化地圖型別也重現了崩潰。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/460207.html
上一篇:使用不同的建構式引數實體化泛型類
下一篇:相同通配符的下限和上限通用約束
