Cómo declarar mapa constante

125

Estoy tratando de declarar constante en Go, pero arroja un error. ¿Podría alguien ayudarme con la sintaxis de declarar una constante en Go?

Este es mi código:

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

Este es el error

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

Respuestas:

153

Su sintaxis es incorrecta. Para hacer un mapa literal (como una pseudo-constante), puede hacer:

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

Dentro de un funcpuede declararlo como:

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

Y en Go no existe un mapa constante. Más información se puede encontrar aquí .

Pruébalo en el parque infantil Go.

squiguy
fuente
1
Esto arroja un non-declaration statement outside function bodytiempo de compilación en realidad. ¿Cómo?
alediaferia
@AlessandroDiaferia No recibo tal error. ¿Cómo lo estás utilizando?
Squiguy
77
@AlessandroDiaferia intente var romanNumeralDict map[int]string = map[int]string{...}en tal caso.
B-Scan
44
@alediaferia obtienes ese error si lo usas :=fuera de una función.
Jeffrey Martinez
1
¿Qué es una "pseudo-constante"?
Garrett
23

Puede crear constantes de muchas maneras diferentes:

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

También puede crear una enumeración constante:

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

No puede crear constantes de mapas, matrices y está escrito en go efectivo :

Las constantes en Go son solo eso, constantes. Se crean en tiempo de compilación, incluso cuando se definen como locales en funciones, y solo pueden ser números, caracteres (runas), cadenas o booleanos. Debido a la restricción de tiempo de compilación, las expresiones que las definen deben ser expresiones constantes, evaluables por el compilador. Por ejemplo, 1 << 3 es una expresión constante, mientras que math.Sin (math.Pi / 4) no se debe a que la llamada a la función math.Sin debe suceder en tiempo de ejecución.

Salvador Dalí
fuente
así que es más como un constexpr C ++ 11 ... ¡por qué math.Sin no es una función constexpr, entonces!
Francesco Dondi
Sus declaraciones son correctas, pero la pregunta era sobre la creación de un mapa que sea constante.
jzer7
55
@ jzer7 ¿puedes explicarme por qué mi respuesta es irrelevante? Me preguntó cómo crear algo, le dije que esto no es posible. Explicó lo que es posible y dio una cita de los documentos por qué exactamente no es posible hacer lo que quiere.
Salvador Dali
12

Puede emular un mapa con un cierre:

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

Pruébalo en el patio de juegos Go

oleber
fuente
44
(TestMostSoldRecommender?)
twotwotwo
1
De hecho, es una posible solución. Sin embargo, dado que el autor no explicó nada (y puso todo dentro de un caso de prueba con un nombre extraño), la respuesta parece incorrecta. La lógica es: (1) Crear una función anónima (2) La función anónima encapsula el map(3) La función anónima devuelve "una función que acepta un int y devuelve una cadena" (4) La función devuelta hace el int -> cadena mapeo utilizando map(5) Ejecute la función anónima inmediatamente y asigne la función devuelta a una variable. Esta variable podría usarse como una función, y el efecto es como un mapa.
Siu Ching Pong -Asuka Kenji-
3

Y como lo sugirió anteriormente Siu Ching Pong -Asuka Kenji con la función que en mi opinión tiene más sentido y te deja con la comodidad del tipo de mapa sin la envoltura de la función:

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

Prueba esto en play.golang.org.

Denis Volin
fuente
-2

Como se indicó anteriormente, definir un mapa como constante no es posible. Pero puede declarar una variable global que es una estructura que contiene un mapa.

La inicialización se vería así:

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
fuente
3
¿Por qué no solo hacer que el mapa sea la variable global? ¿Por qué envolverlo en la estructura?
Huracán Hamilton
3
Esto no hace que el mapa sea constante, todavía puedes hacerloromanNumeralDict.m[1000] = "New value"
brando