Ответ 1
Нет, срезы не могут использоваться в качестве ключей карты, поскольку они не имеют определенного равенства.
Можно ли использовать срезы в качестве ключей?
Есть моя попытка:
h := map[[]string]string{
[]string{"a", "b"} : "ab",
}
компилятор дает мне ошибку invalid map key type []string
. Так что либо это невозможно, либо я объявил это неправильно (если да, то был бы правильный путь?).
Нет, срезы не могут использоваться в качестве ключей карты, поскольку они не имеют определенного равенства.
Однако в качестве ключей карты можно использовать массивы:
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",
}
В зависимости от ваших требований и сложности ваших данных вы можете использовать строку в качестве ключа карты, а затем использовать хэш своего фрагмента в качестве ключа карты.
Приятно, что вы можете использовать эту технику для всего, что можно преобразовать в или из куска байтов.
Вот быстрый способ преобразования вашего фрагмента строк в кусок байта:
[]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
}
Один из способов обойти эту проблему - фактически создать ключ из среза, который имеет хорошо определенные операторы сравнения:
func createKey(s []string) string { return fmt.Sprintf("%q", s) }
m := make(map[string]string)
s := []string{"a","b"}
m[createKey(s)] = "myValue"
Аналогичным образом вам придется создавать функции для создания ключей срезов с типом, отличным от строки.