为了账号安全,请及时绑定邮箱和手机立即绑定

如何防止类型被用作映射键?

如何防止类型被用作映射键?

Go
慕神8447489 2022-01-17 19:53:19
我有一种可以用作映射键的类型,但我想防止这种情况发生。我假设如果该类型包含一个私有成员,那么其他包就不可能,但这似乎仍然有效。使该类型无法用作映射键的最佳方法是什么?type MyType struct {    A *A    b b    preventUseAsKey ?}
查看完整描述

2 回答

?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

我认为不允许将类型用作键没有任何好处。它只是一个可能会或可能不会使用的选项,类型不会因为您禁止将其用作映射键而变得更好或更小或更快。


但如果你想这样做:规范:地图类型:


比较运算符== 和 != 必须为键类型的操作数完全定义;因此键类型不能是函数、映射或切片。


因此,如果您可以违反比较运算符的条款,您就会隐含地得到您想要的。您有struct以下类型的 , 术语struct:


如果结构值的所有字段都是可比较的,则结构值是可比较的。如果它们对应的非空白字段相等,则两个结构值相等。


所以struct值只有在它们的所有字段都是可比较的情况下才具有可比性(因此只能用作映射中的键)。只需添加一个类型不可比较的字段。


切片、映射和函数值不可比较。


因此,例如添加一个类型为切片的字段,您就完成了:


type MyType struct {

    S             string

    i             int

    notComparable []int

}

尝试将上述MyType内容用作密钥:


m := map[MyType]int{}

你得到一个编译时错误:


invalid map key type MyType

笔记:


我写了关于禁止类型作为键没有任何好处的文章。不仅如此:从现在开始,您将无法再对您的类型的值使用比较运算符(因为额外的、不可比较的字段),因此例如您失去了比较这些值的选项:


p1, p2 := MyType{}, MyType{}

fmt.Println(p1 == p2)

编译时错误:


invalid operation: p1 == p2 (struct containing []int cannot be compared)

请注意,通过一个小技巧,您仍然可以保留您的类型的可比较性质,例如,通过不导出您的类型而是嵌入原始类型的包装器类型;并将额外的、不可比较的类型添加到包装器类型中,例如:


type myType struct {

    S string

    i int

}


type MyType struct {

    myType

    notComparable []int

}


func main() {

    p1, p2 := MyType{}, MyType{}

    fmt.Println(p1.myType == p2.myType)

}

这样,您myType可以保持可比性,但仍会阻止导出的包装器MyType类型用作键类型。


查看完整回答
反对 回复 2022-01-17
?
蓝山帝景

TA贡献1843条经验 获得超7个赞

您的类型不应具有可比性,以免不适合作为映射键。


切片、映射和函数值不可比较


请参阅密钥类型:


列表中明显没有切片、映射和函数。这些类型不能使用 比较==,也不能用作映射键。


所以如果你的类型是切片、映射或函数,你应该得到你需要的。

它可能是一个“别名”(定义一个新的命名类型):


type StringSliceWrap []string

type MyFunc func(i int)

该别名不会用作映射键。


2017 年更新:Brad Fitzpatrick 提供此提示(在您的 中添加一个切片struct)以确保您的类型struct不可比较:请参阅play.golang.org:


package main


// disallowEqual is an uncomparable type.

// If you place it first in your struct, you prevent == from

// working on your struct without growing its size. (Don't put it

// at the end; that grows the size of the struct)

type disallowEqual [0]func()


type T struct {

    _ disallowEqual

    Foo string

    Bar int

}


func main() {

    var t1 T

    var t2 T

    println(t1 == t2)

}

T 现在不能用作amp键!


查看完整回答
反对 回复 2022-01-17
  • 2 回答
  • 0 关注
  • 151 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信