Как я могу создать карту голангов в одной инструкции?

Это мой код:

var keys map[int]string
keys = make(map[int]string)

keys[1] = "aa"
keys[2] = "ab"
keys[3] = "ac"
keys[4] = "ba"
keys[5] = "bb"
keys[6] = "bc"
keys[7] = "ca"
keys[8] = "cb"
keys[9] = "cc"

Можно ли сделать одно и то же в одном утверждении и/или в одной строке?

Ответ 1

Да, вы можете создать карту с одним оператором (называемый составной литерал в спецификации):

var keys = map[int]string{
    1: "aa",
    2: "ab",
    3: "ac",
    4: "ba",
    5: "bb",
    6: "bc",
    7: "ca",
    8: "cb",
    9: "cc",
}

Или, если вы находитесь внутри функции, вы можете использовать короткую декларацию :

keys := map[int]string{
    1: "aa",
    2: "ab",
    3: "ac",
    4: "ba",
    5: "bb",
    6: "bc",
    7: "ca",
    8: "cb",
    9: "cc",
}

Ответ 2

Когда есть логика между клавишами и значениями, вы также можете использовать цикл для инициализации карты. "Положите" логику в тело цикла. Это может быть значительно короче, чем использование составного литерала, перечисляющего все пары ключ-значение, особенно если количество пар ключ-значение велико.

Ваш пример может быть реализован с помощью этого:

m := map[int]string{}
for i := 0; i < 9; i++ {
    m[i+1] = string("abc"[i/3]) + string("abc"[i%3])
}
fmt.Println(m)

Вывод (попробуйте на Go Playground):

map[5:bb 8:cb 4:ba 2:ab 3:ac 6:bc 7:ca 9:cc 1:aa]

Вариант этого решения (с использованием другой логической реализации):

m := map[int]string{}
for i := 0; i < 9; i++ {
    m[i+1] = "abc"[i/3:i/3+1] + "abc"[i%3:i%3+1]
}
fmt.Println(m)

Вывод - это "тот же". Попробуйте этот вариант на Go Playground.

И еще больше решений, теперь публикуя только тело цикла (ссылки на игровые площадки: другое # 1, другое # 2):

// Another #1:
m[i+1] = fmt.Sprintf("%c%c", "abc"[i/3], "abc"[i%3])
// Another #2:
m[i+1] = fmt.Sprintf("%c%c", 'a'+i/3, 'a'+i%3)

В другом подходе могут использоваться 2 цикла (встроенные), которые генерируют значение, и вычисляет ключ из значения:

for i := 'a'; i <= 'c'; i++ {
    for j := 'a'; j <= 'c'; j++ {
        m[int((i-'a')*3+j-'a'+1)] = string(i) + string(j)
    }
}

Попробуйте это на Go Playground.

Если количество значений невелико, другой жизнеспособный подход может состоять в том, чтобы перечислить все элементы в одном значении string и использовать функцию подсекции (которая эффективна, поскольку новые массивы поддержки не будут созданы, массив поддержки строки разделяются):

const s = "aaabacbabbbccacbcc"

m := map[int]string{}
for i := 0; i < 9; i++ {
    m[i+1] = s[i*2 : i*2+2]
}
fmt.Println(m)

Выход (попробуйте это на Go Playground):

map[9:cc 1:aa 2:ab 5:bb 8:cb 3:ac 4:ba 6:bc 7:ca]

Также обратите внимание, что если ключ имеет тип int, а набор ключей (более или менее) смежный, часто эффективнее (как память, так и производительность) использовать вместо этого срез:

m := make([]string, 10)
for i := 0; i < 9; i++ {
    m[i+1] = fmt.Sprintf("%c%c", 'a'+i/3, 'a'+i%3)
}
fmt.Printf("%q\n", m)

m2 := []string{"", "aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"}
fmt.Printf("%q\n", m2)

m3 := []string{1: "aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"}
fmt.Printf("%q\n", m3)

Выход (попробуйте на Go Playground):

["" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc"]
["" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc"]
["" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc"]

Как вы можете видеть в третьем примере m3, вы можете использовать необязательные индексы в составном литерале, чтобы указать индекс следующего значения. Подробнее об этом здесь: Ключевые элементы в инициализации массива golang

Ответ 3

Мой предпочтительный подход - это сложный литерал в коротком объявлении переменной. В некоторых случаях функция может помочь уменьшить беспорядок.

package main

import (
    "fmt"
)

// initMap initializes a map with an integer key starting at 1
func initMap(sa []string) map[int]string {
    m := make(map[int]string, len(sa))
    for k, v := range sa {
        m[k+1] = v // add 1 to k as it is starting at base 0
    }
    return m
}

// main is the entry point of any go application
func main() {
    // My preferred approach is a composite literal in a short variable declaration
    keys := map[int]string{1: "aa", 2: "ab", 3: "ac", 4: "ba", 5: "bb", 6: "bc", 7: "ca", 8: "cb", 9: "cc"}
    fmt.Println(keys)

    // Using a function to initialize the map might help to avoid clutter
    keys2 := initMap([]string{"aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"})
    fmt.Println(keys2)
}

Посмотрите на действие в https://play.golang.org/p/Rrb9ChBkXW