Как объявить постоянную карту

126

Я пытаюсь объявить константу в Go, но выдает ошибку. Может ли кто-нибудь помочь мне с синтаксисом объявления константы в Go?

Это мой код:

const romanNumeralDict map[int]string = {
  1000: "M",
  900 : "CM",
  500 : "D",
  400 : "CD",
  100 : "C",
  90  : "XC",
  50  : "L",
  40  : "XL",
  10  : "X",
  9   : "IX",
  5   : "V",
  4   : "IV",
  1   : "I",
}

Это ошибка

# command-line-arguments
./Roman_Numerals.go:9: syntax error: unexpected {
самоль
источник

Ответы:

154

Ваш синтаксис неверен. Чтобы создать буквальную карту (как псевдоконстанту), вы можете:

var romanNumeralDict = map[int]string{
  1000: "M",
  900 : "CM",
  500 : "D",
  400 : "CD",
  100 : "C",
  90  : "XC",
  50  : "L",
  40  : "XL",
  10  : "X",
  9   : "IX",
  5   : "V",
  4   : "IV",
  1   : "I",
}

Внутри funcвы можете объявить это так:

romanNumeralDict := map[int]string{
...

А в Go нет такой вещи, как постоянная карта. Более подробную информацию можно найти здесь .

Попробуйте это на игровой площадке для игры в го.

squiguy
источник
1
На non-declaration statement outside function bodyсамом деле это вызывает ошибку во время компиляции. Как придешь?
alediaferia
@AlessandroDiaferia Я не получаю такой ошибки. Как ты им пользуешься?
squiguy
7
@AlessandroDiaferia попробуй var romanNumeralDict map[int]string = map[int]string{...}в таком случае.
B-Scan
4
@alediaferia вы получите эту ошибку при использовании :=вне функции.
Джеффри Мартинес
1
Что такое «псевдоконстанта»?
Garrett
24

Вы можете создавать константы разными способами:

const myString = "hello"
const pi = 3.14 // untyped constant
const life int = 42 // typed constant (can use only with ints)

Вы также можете создать константу перечисления:

const ( 
   First = 1
   Second = 2
   Third = 4
)

Вы не можете создавать константы карт, массивов и это записано на эффективном ходу :

Константы в Go просто постоянны. Они создаются во время компиляции, даже если они определены как локальные переменные в функциях, и могут быть только числами, символами (рунами), строками или логическими значениями. Из-за ограничения времени компиляции определяющие их выражения должны быть константными выражениями, вычисляемыми компилятором. Например, 1 << 3 - постоянное выражение, а math.Sin (math.Pi / 4) - не потому, что вызов функции math.Sin должен происходить во время выполнения.

Сальвадор Дали
источник
так что это больше похоже на constexpr C ++ 11 ... тогда почему math.Sin не является функцией constexpr!
Francesco Dondi
Ваши утверждения верны, но вопрос был о создании постоянной карты.
jzer7
5
@ jzer7, можешь мне объяснить, почему мой ответ неуместен? Он спросил, как что-то создать, я ему сказал, что это невозможно. Объяснил, что возможно, и привел цитату из документации, почему именно невозможно делать то, что он хочет.
Сальвадор Дали,
12

Вы можете эмулировать карту с закрытием:

package main

import (
    "fmt"
)

// http://stackoverflow.com/a/27457144/10278

func romanNumeralDict() func(int) string {
    // innerMap is captured in the closure returned below
    innerMap := map[int]string{
        1000: "M",
        900:  "CM",
        500:  "D",
        400:  "CD",
        100:  "C",
        90:   "XC",
        50:   "L",
        40:   "XL",
        10:   "X",
        9:    "IX",
        5:    "V",
        4:    "IV",
        1:    "I",
    }

    return func(key int) string {
        return innerMap[key]
    }
}

func main() {
    fmt.Println(romanNumeralDict()(10))
    fmt.Println(romanNumeralDict()(100))

    dict := romanNumeralDict()
    fmt.Println(dict(400))
}

Попробуйте на игровой площадке Go

oleber
источник
4
(TestMostSoldRecommender?)
twotwotwo,
1
Фактически, это возможное решение. Однако, поскольку автор ничего не объяснил (и поместил все в тестовый пример со странным названием), ответ выглядит неверным. Логика такова: (1) Создайте анонимную функцию (2) Анонимная функция инкапсулирует map(3) Анонимная функция возвращает «функцию, которая принимает int и возвращает строку» (4) Возвращенная функция выполняет int -> string отображение с помощью map(5) Немедленное выполнение анонимной функции и присвоение возвращаемой функции переменной. Эта переменная может использоваться как функция, а эффект подобен карте.
Сиу Чинг Понг - Асука Кенджи -
3

И, как было предложено выше Сиу Чинг Понг-Асука Кенджи с функцией, которая, на мой взгляд, имеет больше смысла и оставляет вам удобство типа карты без оболочки функции:

   // romanNumeralDict returns map[int]string dictionary, since the return
       // value is always the same it gives the pseudo-constant output, which
       // can be referred to in the same map-alike fashion.
       var romanNumeralDict = func() map[int]string { return map[int]string {
            1000: "M",
            900:  "CM",
            500:  "D",
            400:  "CD",
            100:  "C",
            90:   "XC",
            50:   "L",
            40:   "XL",
            10:   "X",
            9:    "IX",
            5:    "V",
            4:    "IV",
            1:    "I",
          }
        }

        func printRoman(key int) {
          fmt.Println(romanNumeralDict()[key])
        }

        func printKeyN(key, n int) {
          fmt.Println(strings.Repeat(romanNumeralDict()[key], n))
        }

        func main() {
          printRoman(1000)
          printRoman(50)
          printKeyN(10, 3)
        }

Попробуйте это на play.golang.org.

Денис Волин
источник
-2

Как указано выше, определить карту как постоянную невозможно. Но вы можете объявить глобальную переменную, которая представляет собой структуру, содержащую карту.

Инициализация будет выглядеть так:

var romanNumeralDict = struct {
    m map[int]string
}{m: map[int]string {
    1000: "M",
    900: "CM",
    //YOUR VALUES HERE
}}

func main() {
    d := 1000
    fmt.Printf("Value of Key (%d): %s", d, romanNumeralDict.m[1000])
}
Inde
источник
3
Почему бы просто не сделать карту глобальной переменной? Зачем оборачивать его в структуру?
Ураган Гамильтон,
3
Это не делает карту постоянной, вы все еще можете сделать этоromanNumeralDict.m[1000] = "New value"
Брандо