Я реализовал набор на основе универсального, и все в порядке, пока я не использую структуру в качестве элемента набора вместо базового типа. Я получил ошибку компиляции.
го версия: 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{}{} }
, он может быть скомпилирован успешно.я думаю, что это странно, может кто-нибудь объяснить, пожалуйста?
В качестве обходного пути (пока это не будет исправлено) вы можете использовать ручное преобразование перед передачей s
в maps.Copy()
следующим образом: maps.Copy(map[T]struct{}(s), another)
Похоже на эта ошибка компилятора. Вероятно, это будет исправлено в Go 1.19 и перенесено в Go 1.18.1.
А пока я бы рекомендовал просто отказаться от пакета 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.Equal
или 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.
похоже на Эта проблема