Jak zadeklarować stałą mapę


126

Próbuję zadeklarować stałą w Go, ale generuje błąd. Czy ktoś mógłby mi pomóc ze składnią deklarowania stałej w Go?

To jest mój kod:

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",
}

To jest błąd

# command-line-arguments
./Roman_Numerals.go:9: syntax error: unexpected {

Odpowiedzi:


154

Twoja składnia jest nieprawidłowa. Aby utworzyć mapę dosłowną (jako pseudo-stałą), możesz wykonać:

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",
}

Wewnątrz funcmożna to zadeklarować w następujący sposób:

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

A w Go nie ma czegoś takiego jak stała mapa. Więcej informacji można znaleźć tutaj .

Wypróbuj na placu zabaw Go.


1
To non-declaration statement outside function bodyfaktycznie rzuca w czasie kompilacji. Dlaczego?
alediaferia,

@AlessandroDiaferia nie dostaję takiego błędu. Jak go używasz?
squiguy

7
@AlessandroDiaferia spróbuj var romanNumeralDict map[int]string = map[int]string{...}w takim przypadku.
B-Scan

4
@alediaferia pojawia się ten błąd, jeśli używasz :=poza funkcją.
Jeffrey Martinez

1
Co to jest „pseudo-stała”?
Garrett

23

Możesz tworzyć stałe na wiele różnych sposobów:

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

Możesz również utworzyć stałą wyliczeniową:

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

Nie można tworzyć stałych map, tablic i jest napisane w efektywny sposób :

Stałe w Go są po prostu takie - stałe. Są tworzone w czasie kompilacji, nawet jeśli są zdefiniowane jako lokalne w funkcjach i mogą być tylko liczbami, znakami (runami), łańcuchami lub wartościami logicznymi. Ze względu na ograniczenie czasu kompilacji wyrażenia, które je definiują, muszą być wyrażeniami stałymi, możliwymi do oszacowania przez kompilator. Na przykład 1 << 3 jest wyrażeniem stałym, podczas gdy math.Sin (math.Pi / 4) nie jest wynikiem wywołania funkcji math.Sin w czasie wykonywania.


więc jest bardziej podobny do constexpr w C ++ 11 ... dlaczego więc matematyka. sin nie jest funkcją constexpr!
Francesco Dondi

Twoje wypowiedzi są poprawne, ale chodziło o stworzenie mapy, która jest stała.
jzer7

5
@ jzer7 czy możesz mi wyjaśnić, dlaczego moja odpowiedź jest nieistotna? Zapytał, jak coś stworzyć, powiedziałem mu, że to niemożliwe. Wyjaśnił, co jest możliwe i przytoczył dokumentację, dlaczego dokładnie nie jest możliwe zrobienie tego, czego chce.
Salvador Dali

12

Możesz emulować mapę z zamknięciem:

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

Wypróbuj na placu zabaw Go


4
(TestMostSoldRecommender?)
twotwotwo

1
W rzeczywistości jest to możliwe rozwiązanie. Ponieważ jednak autor niczego nie wyjaśnił (i umieścił wszystko w dziwnie nazwanym przypadku testowym), odpowiedź wygląda nieprawidłowo. Logika jest następująca: (1) Utwórz funkcję anonimową (2) Funkcja anonimowa hermetyzuje map(3) Funkcja anonimowa zwraca „funkcję, która przyjmuje int i zwraca ciąg znaków” (4) Zwracana funkcja wykonuje int -> string mapowanie przy użyciu map(5) Natychmiastowe wykonanie funkcji anonimowej i przypisanie zwróconej funkcji do zmiennej. Ta zmienna może być używana jak funkcja, a efekt jest jak mapa.
Siu Ching Pong -Asuka Kenji-

3

I jak zasugerowała powyżej Siu Ching Pong -Asuka Kenji z funkcją, która moim zdaniem ma więcej sensu i pozostawia wygodę typu mapy bez oplotu funkcji wokół:

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

Spróbuj tego na play.golang.org.


-2

Jak stwierdzono powyżej, zdefiniowanie mapy jako stałej nie jest możliwe. Ale możesz zadeklarować zmienną globalną, która jest strukturą zawierającą mapę.

Inicjalizacja wyglądałaby następująco:

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
Dlaczego nie uczynić mapy zmienną globalną? Po co zawijać to w strukturę?
Huragan Hamilton

3
To nie sprawia, że ​​mapa jest stała, nadal możesz to zrobićromanNumeralDict.m[1000] = "New value"
brando
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.