Як оголосити постійну карту


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 немає такого поняття, як постійна карта. Більше інформації можна знайти тут .

Спробуйте це на ігровому майданчику Go.


1
Це non-declaration statement outside function bodyфактично кидає час компіляції. Як це?
аледіаферія

@AlessandroDiaferia Я не отримую такої помилки. Як ти це використовуєш?
squiguy

7
@AlessandroDiaferia спробуйте var romanNumeralDict map[int]string = map[int]string{...}в такому випадку.
B-Scan

4
@alediaferia ви отримуєте цю помилку, якщо користуєтеся :=поза функцією.
Джеффрі Мартінес

1
Що таке "псевдоконстанта"?
Гаррет

23

Константи можна створювати різними способами:

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 має відбуватися під час виконання.


тому це більше схоже на C ++ 11 constexpr ... чому math.Sin - це не функція constexpr!
Франческо Донді

Ваші твердження правильні, але питання полягало у створенні постійної карти.
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


4
(TestMostSoldRecommender?)
twotwotwo

1
Це насправді можливе рішення. Однак, оскільки автор нічого не пояснив (і поклав усе все у дивно названий тестовий випадок), відповідь виглядає неправильним. Логіка полягає в наступному: (1) Створення анонімної функції (2) Анонімна функція інкапсулює map(3) Анонімна функція повертає "функцію, яка приймає int і повертає рядок" (4) Повернута функція виконує рядок int -> відображення за допомогою map(5) Негайно виконайте анонімну функцію та призначте повернуту функцію змінній. Цю змінну можна використовувати як функцію, а ефект - як карту.
Siu Ching Pong -Asuka Kenji-

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])
}

3
Чому б не просто зробити карту глобальною змінною? Навіщо загортати його в структуру?
Ураган Гамільтон

3
Це не робить карту постійною, ви все ще можете зробитиromanNumeralDict.m[1000] = "New value"
брендо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.