How to declare a constant map in Golang?

huangapple go评论83阅读模式
英文:

How to declare a constant map in Golang?

问题

我正在尝试在Go语言中声明一个常量,但是它报错了。

这是我的代码:

const myMap = map[int]string{
	1: "one",
	2: "two",
	3: "three",
}

这是错误信息:

map[int]string{...}(类型为map[int]string的值)不是常量
英文:

I am trying to declare to constant in Go, but it is throwing an error.

This is my code:

const myMap = map[int]string{
	1: "one",
	2: "two",
	3: "three",
}

This is the error

map[int]string{…} (value of type map[int]string) is not constant

答案1

得分: 250

在Go语言中,不幸的是,map不能被声明为const。你可以使用var关键字将其声明为普通变量,如下所示:

var myMap = map[int]string{
	1: "one",
	2: "two",
	3: "three",
}

在函数内部,你可以使用短变量声明语法进行声明:

func main() {
	myMap := map[int]string{
		1: "one",
		2: "two",
		3: "three",
	}
}

在Go playground上试一试。

英文:

In Go, a map unfortunately cannot be const. You can declare it as a regular variable like this with the var keyword:

var myMap = map[int]string{
	1: "one",
	2: "two",
	3: "three",
}

Inside a function, you may declare it with the short assignment syntax:

func main() {
	myMap := map[int]string{
		1: "one",
		2: "two",
		3: "three",
	}
}

Try it out on the Go playground.

答案2

得分: 35

你可以用多种方式创建常量:

const myString = "hello"
const pi = 3.14 // 无类型常量
const life int = 42 // 有类型常量(只能用于整数)

你还可以创建枚举常量:

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

你不能创建映射和数组的常量,这在《Effective Go》中有所说明:

在Go中,常量就是常量。它们在编译时创建,即使在函数中定义为局部变量,也只能是数字、字符(符文)、字符串或布尔值。由于编译时的限制,定义常量的表达式必须是常量表达式,可以由编译器计算出结果。例如,1<<3是一个常量表达式,而math.Sin(math.Pi/4)不是,因为调用math.Sin的函数需要在运行时发生。

英文:

You can create constants in many different ways:

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

You can also create a enum constant:

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

You can not create constants of maps, arrays and it is written in effective go:

> Constants in Go are just that—constant. They are created at compile
> time, even when defined as locals in functions, and can only be
> numbers, characters (runes), strings or booleans. Because of the
> compile-time restriction, the expressions that define them must be
> constant expressions, evaluatable by the compiler. For instance, 1<<3
> is a constant expression, while math.Sin(math.Pi/4) is not because the
> function call to math.Sin needs to happen at run time.

答案3

得分: 18

你可以使用闭包来模拟一个映射:

package main

import (
	"fmt"
)

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

func romanNumeralDict() func(int) string {
	// innerMap 被闭包捕获,返回的闭包函数中使用了 innerMap
	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 playground 上试一试

英文:

You may emulate a map with a closure:

package main

import (
	&quot;fmt&quot;
)

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

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

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

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

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

Try it on the Go playground

答案4

得分: 4

根据Siu Ching Pong - Asuka Kenji的建议,以下是一个更合理的函数,它使用了地图类型,而没有在函数周围添加包装器:

// romanNumeralDict 返回 map[int]string 字典,由于返回值始终相同,它提供了伪常量的输出,可以以类似地图的方式引用。
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上尝试一下。

英文:

And as suggested above by Siu Ching Pong -Asuka Kenji with the function which in my opinion makes more sense and leaves you with the convenience of the map type without the function wrapper around:

   // 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: &quot;M&quot;,
            900:  &quot;CM&quot;,
            500:  &quot;D&quot;,
            400:  &quot;CD&quot;,
            100:  &quot;C&quot;,
            90:   &quot;XC&quot;,
            50:   &quot;L&quot;,
            40:   &quot;XL&quot;,
            10:   &quot;X&quot;,
            9:    &quot;IX&quot;,
            5:    &quot;V&quot;,
            4:    &quot;IV&quot;,
            1:    &quot;I&quot;,
          }
        }
    
        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)
        }

Try this at play.golang.org.

答案5

得分: 0

我知道这段代码看起来不太好看,但你可以使用匿名结构体和闭包来实现类似于常量映射的功能:

type MapGet[T any, V any] func(T) (V, bool)

var (
	myMap = struct {
		Get MapGet[int, string]
	}{
		Get: func(mp map[int]string) MapGet[int, string] {
			return func(key int) (string, bool) {
				v, found := mp[key]
				return v, found
			}
		}(map[int]string{
			1: "one",
			2: "two",
			3: "three",
		}),
	}
)

func main() {
    v, _ := myMap.Get(1)
    fmt.Println(v)
}

你可以在这里查看代码:https://goplay.tools/snippet/SrAMRsBOPn9

英文:

I know this is not the nicest looking code, but you can achieve somewhat of a constant map-like thing using anonymous structs and closures:

Voila!

type MapGet[T any, V any] func(T) (V, bool)

var (
	myMap = struct {
		Get MapGet[int, string]
	}{
		Get: func(mp map[int]string) MapGet[int, string] {
			return func(key int) (string, bool) {
				v, found := mp[key]
				return v, found
			}
		}(map[int]string{
			1: &quot;one&quot;,
			2: &quot;two&quot;,
			3: &quot;three&quot;,
		}),
	}
)

func main() {
    v, _ := myMap.Get(1)
    fmt.Println(v)
}

https://goplay.tools/snippet/SrAMRsBOPn9

答案6

得分: -5

如上所述,无法将地图定义为常量。但是,您可以声明一个全局变量,该变量是一个包含地图的结构体。

初始化的代码如下所示:

var romanNumeralDict = struct {
    m map[int]string
}{m: map[int]string {
    1000: "M",
    900: "CM",
    //在这里添加您的值
}}

func main() {
    d := 1000
    fmt.Printf("键(%d)的值为:%s", d, romanNumeralDict.m[1000])
}
英文:

As stated above to define a map as constant is not possible.
But you can declare a global variable which is a struct that contains a map.

The Initialization would look like this:

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

func main() {
    d := 1000
    fmt.Printf(&quot;Value of Key (%d): %s&quot;, d, romanNumeralDict.m[1000])
}

huangapple
  • 本文由 发表于 2013年8月21日 02:15:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/18342195.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定