Como declarar mapa constante

125

Estou tentando declarar constante no Go, mas está lançando um erro. Alguém poderia me ajudar com a sintaxe de declarar uma constante no Go?

Este é o meu 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 é o erro

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

Respostas:

153

Sua sintaxe está incorreta. Para criar um mapa literal (como uma pseudo-constante), você pode:

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 um funcvocê pode declarar como:

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

E no Go não existe um mapa constante. Mais informações podem ser encontradas aqui .

Experimente no playground Go.

esquizofrênico
fonte
1
Isso lança um non-declaration statement outside function bodytempo de compilação na verdade. Por quê?
Alediaferia
@AlessandroDiaferia Não recebo esse erro. Como você está usando isso?
squiguy
7
@AlessandroDiaferia tente var romanNumeralDict map[int]string = map[int]string{...}nesse caso.
B-Scan.
4
@alediaferia você recebe esse erro se estiver usando :=fora de uma função.
Jeffrey Martinez
1
O que é uma "pseudo-constante"?
Garrett
23

Você pode criar constantes de várias maneiras diferentes:

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

Você também pode criar uma constante enum:

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

Você não pode criar constantes de mapas, matrizes e está escrito de forma eficaz :

As constantes em Go são exatamente isso - constantes. Eles são criados em tempo de compilação, mesmo quando definidos como locais em funções, e podem ser apenas números, caracteres (runas), strings ou booleanos. Devido à restrição de tempo de compilação, as expressões que os definem devem ser expressões constantes, avaliadas pelo compilador. Por exemplo, 1 << 3 é uma expressão constante, enquanto math.Sin (math.Pi / 4) não ocorre porque a chamada de função para math.Sin precisa ocorrer em tempo de execução.

Salvador Dalí
fonte
então é mais como um constexpr C ++ 11 ... por que math.Sin não é uma função constexpr, então!
Francesco Dondi
Suas declarações estão corretas, mas a pergunta era sobre a criação de um mapa constante.
jzer7
5
@ jzer7 você pode me explicar por que minha resposta é irrelevante? Ele perguntou como criar algo, eu disse a ele que isso não é possível. Explicou o que é possível e citou os documentos por que exatamente não é possível fazer o que ele deseja.
Salvador Dali
12

Você pode emular um mapa com um fechamento:

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

Experimente no playground Go

oleber
fonte
4
(TestMostSoldRecommender?)
twotwotwo
1
É de fato uma solução possível. No entanto, como o autor não explicou nada (e colocou tudo em um caso de teste com nome estranho), a resposta parece incorreta. A lógica é: (1) Criar uma função anônima (2) A função anônima encapsula o map(3) A função anônima retorna "uma função que aceita um int e retorna uma string" (4) A função retornada faz o int -> string mapeamento usando o map(5) Execute a função anônima imediatamente e atribua a função retornada a uma variável. Essa variável pode ser usada como uma função e o efeito é como um mapa.
Siu Ching Pong -Asuka Kenji-
3

E como sugerido acima por Siu Ching Pong -Asuka Kenji com a função que, na minha opinião, faz mais sentido e deixa você com a conveniência do tipo de mapa sem o wrapper de função:

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

Tente isso em play.golang.org.

Denis Volin
fonte
-2

Como mencionado acima, para definir um mapa como constante, não é possível. Mas você pode declarar uma variável global que é uma estrutura que contém um mapa.

A inicialização ficaria assim:

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
fonte
3
Por que não apenas tornar o mapa a variável global? Por que envolvê-lo na estrutura?
Hurricane Hamilton
3
Isso não torna o mapa constante, você ainda pode fazê-loromanNumeralDict.m[1000] = "New value"
brando