【问题标题】:How to declare a constant map in Golang?如何在 Golang 中声明一个常量映射?
【发布时间】:2013-08-22 22:13:22
【问题描述】:

我试图在 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 {

【问题讨论】:

标签: go


【解决方案1】:

您的语法不正确。要制作文字映射(作为伪常量),您可以这样做:

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 中没有常量映射这样的东西。更多信息可以在here找到。

Try it out on the Go playground.

【讨论】:

  • 这实际上在编译时抛出了non-declaration statement outside function body。怎么会?
  • @AlessandroDiaferia 我没有收到这样的错误。你是怎么用的?
  • @AlessandroDiaferia 在这种情况下尝试使用var romanNumeralDict map[int]string = map[int]string{...}
  • @alediaferia 如果在函数外使用:=,则会出现该错误。
  • 什么是“伪常数”?
【解决方案2】:

您可以通过多种不同方式创建常量:

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
)

你不能创建映射、数组的常量,它写在effective go

Go 中的常量就是常量。它们是在编译时创建的 时间,即使在函数中定义为局部变量,也只能是 数字、字符(符文)、字符串或布尔值。由于 编译时限制,定义它们的表达式必须是 常量表达式,可由编译器计算。例如,1

【讨论】:

  • 所以它更像是一个 C++11 的 constexpr ......那么为什么 math.Sin 不是一个 constexpr 函数!
  • 您的陈述是正确的,但问题是关于创建一个不变的地图。
  • @jzer7 你能解释一下为什么我的回答无关紧要吗?他问如何创造一些东西,我告诉他这是不可能的。解释了什么是可能的,并从文档中引用了为什么不能做他想做的事。
【解决方案3】:

您可以模拟带有闭包的地图:

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

Try it on the Go playground

【讨论】:

  • (TestMostSoldRecommender?)
  • 其实是一种可能的解决方案。但是,由于作者没有解释任何内容(并将所有内容都放在一个名称怪异的测试用例中),因此答案看起来不正确。逻辑是:(1)创建匿名函数(2)匿名函数封装map(3)匿名函数返回“一个接受int并返回字符串的函数”(4)返回的函数做int -> 使用map 进行字符串映射 (5) 立即执行匿名函数并将返回的函数赋值给一个变量。这个变量可以像函数一样使用,效果像地图。
【解决方案4】:

正如上面Siu Ching Pong -Asuka Kenji 所建议的那样,我认为这个函数更有意义,并且在没有函数包装的情况下为您提供了地图类型的便利:

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

Try this at play.golang.org.

【讨论】:

    【解决方案5】:

    如上所述,将映射定义为常量是不可能的。 但是你可以声明一个全局变量,它是一个包含映射的结构体。

    初始化如下所示:

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

    【讨论】:

    • 为什么不把地图设为全局变量呢?为什么要将它包装在结构中?
    • 这不会使地图保持不变,您仍然可以这样做romanNumeralDict.m[1000] = "New value"
    猜你喜欢
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多