使用映射时,请使用1.18通用编译错误。

发布于 2025-01-19 13:42:02 字数 1259 浏览 0 评论 0原文

我实现了基于通用的集合,一切正常,直到我将struct用作集合元素而不是基本类型为止。我有一个补充错误。

GO版本:GO版本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
  • 如果只有1个字段,则可以将其汇编成功。
  • 如果我使用for V:= range另一个{s [v] = struct {} {}}},它可以成功地编译。

我认为这很奇怪,有人可以解释吗?

I implemented a Set based on generic, and everything ok until i use struct as Set element instead of base type. I got an compliation error.

go version: go version go1.18 windows/amd64

Below code is failed to complie in function 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)
}

when run it:

> 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
  • if Key only has 1 field, it can be compiled successful.
  • if i use for v := range another { s[v]=struct{}{} }, it can be compiled successful.

i think it's strange, can someone explain please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

海夕 2025-01-26 13:42:02

看起来像此编译器错误。它已固定在GO 1.19中,并备份为1.18.2。

如果您使用的是较旧版本,我建议您简单地放弃地图软件包,然后手工做事,就像您已经尝试过一样。这只是一个简单的循环:

func (s Set[T]) AddSet(another Set[T]) {
    for k := range another {
        s[k] = struct{}{}
    }
}

@icza对将命名地图类型明确转换为其基础类型的评论也有效:

maps.Copy(map[T]struct{}(s), another)

如果您使用的是期望多个地图类型参数(具有相同约束)的函数,则为maps.qual.qual.qual.equal在

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))
}

​nofollow noreferrer“>再现也使用具有Len&gt; = 2的阵列实例化的参数化地图类型。

It looks like this compiler error. It is fixed in Go 1.19 and backported to Go 1.18.2.

If you are on an older version, I'd recommend simply forgoing the maps package and doing things by hand, as you already tried. It's just a simple loop:

func (s Set[T]) AddSet(another Set[T]) {
    for k := range another {
        s[k] = struct{}{}
    }
}

@icza's comment of explicitly converting the named map type to its underlying type also works:

maps.Copy(map[T]struct{}(s), another)

In case you use functions that expect more than one map type parameter (with the same constraints), as maps.Equal or maps.EqualFunc, you have to convert both arguments:

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))
}

It seems the crash was reproduced also with parametrized map types instantiated with arrays with len >= 2.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文