Go 切片作为地图中的关键点

Go 切片作为地图中的关键点,go,Go,可以将切片用作关键点吗 我的尝试是: h := map[[]string]string{ []string{"a", "b"} : "ab", } 编译器给了我一个错误无效的映射键类型[]字符串。因此,要么是不可能,要么是我错误地声明了它(如果是这样,正确的方法是什么?)不,切片不能用作映射键,因为它们没有定义相等项。但是,使用数组作为映射键: package main import "fmt" func main() { m := make(map[[2]int]bool)

可以将切片用作关键点吗

我的尝试是:

h := map[[]string]string{
  []string{"a", "b"} : "ab",
}

编译器给了我一个错误
无效的映射键类型[]字符串
。因此,要么是不可能,要么是我错误地声明了它(如果是这样,正确的方法是什么?)

不,切片不能用作映射键,因为它们没有定义相等项。

但是,使用数组作为映射键:

package main

import "fmt"

func main() {
    m := make(map[[2]int]bool)
    m[[2]int{1, 2}] = false
    fmt.Printf("%v", m)
}

Volker已经告诉我这是不可能的,我将用规范中的例子详细说明为什么会这样


告诉你:

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

它已经告诉您切片不能是键,但您也可以在以下位置检查它:

切片、贴图和函数值不可比较


这意味着切片不能是键,数组可以是键。例如,您可以编写:

h := map[[2]string]string{
  [2]string{"a", "b"} : "ab",
}

解决此问题的一种方法是从具有定义良好的比较运算符的切片实际创建一个键:

func createKey(s []string) string { return fmt.Sprintf("%q", s) }

m := make(map[string]string)
s := []string{"a","b"}
m[createKey(s)] = "myValue"

以类似的方式,您必须创建函数来创建类型不同于字符串的片的键。

根据您的要求和数据的复杂性,您可以使用字符串作为映射键,然后使用片的哈希作为映射键

很好的一点是,您可以将此技术用于任何可以转换为字节片或从字节片转换而来的内容

以下是将字符串片段转换为字节片段的快速方法:

[]byte(strings.Join([]string{},""))
下面是一个使用SHA1的示例:

type ByteSliceMap struct {
    buf *bytes.Buffer
    m   map[string][]byte
}

func (b *ByteSliceMap) key(buf []byte) string {
    h := sha1.New()
    h.Write(buf)
    sum := h.Sum(nil)
    return fmt.Sprintf("%x", sum)
}

func (t *ByteSliceMap) value(key []byte) (value []byte, ok bool) {
    value, ok = t.m[t.key(key)]
    return
}


func (t *ByteSliceMap) add(key, value []byte) {
    if t.m == nil {
        t.m = make(map[string][]byte)
    }
    t.m[t.key(key)] = value
}

这是一个糟糕的选择。即使检查键是否存在也需要在GC上加载,因为必须创建一个新对象才能执行查找。不酷。这是个糟糕的选择。即使检查键是否存在,也需要在GC上加载,因为必须创建多个对象才能进行查找。@DrewO'Meara您有什么建议或替代方法吗?此答案结合了两种技术:使用哈希从长字节片构建短字节片键和将字节片转换为字符串。将字节片转换为字符串
string(myByteSlice)
就足够了。转换执行动态分配(->GC)。散列部分可以重构为不执行分配的方式(通过使用数组和使用段的快速散列)。同时
字符串
可以用作键,例如
map[string]bool
-字节片不能
map[[]byte]bool
。但是
字符串
[]字节
可以互换转换,所以这是可行的:
bs:=[]字节{0xde,0xad,0xbe,0xef};mymap[字符串(bs)]=true