【问题标题】:Declare a constant array声明一个常量数组
【发布时间】:2012-10-19 16:51:09
【问题描述】:

我试过了:

const ascii = "abcdefghijklmnopqrstuvwxyz"
const letter_goodness []float32  = { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }
const letter_goodness  = { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }
const letter_goodness = []float32 { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }

第一个声明和初始化工作正常,但第二个、第三个和第四个不起作用。

如何声明和初始化一个 const 浮点数组?

【问题讨论】:

    标签: arrays go constants


    【解决方案1】:

    数组本质上不是不可变的;你不能让它保持不变。

    你能得到的最近的是:

    var letter_goodness = [...]float32 {.0817, .0149, .0278, .0425, .1270, .0223, .0202, .0609, .0697, .0015, .0077, .0402, .0241, .0675, .0751, .0193, .0009, .0599, .0633, .0906, .0276, .0098, .0236, .0015, .0197, .0007 }
    

    注意[...] 而不是[]:它确保你得到一个(固定大小)数组而不是切片。所以值不是固定的,但大小是固定的。

    【讨论】:

    • 只是为了澄清:[...]T 语法是 [123]T 的糖。它创建一个固定大小的数组,但让编译器确定其中有多少元素。
    • 我猜允许常量数组需要更新类型系统。否则,如果你定义了一个函数f(xs [5]int),你将不知道传递的数组是常量还是可变的。
    • 令人惊讶的是,编译器会为每个数组条目生成初始化代码...
    【解决方案2】:

    来自Effective Go

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

    切片和数组总是在运行时计算:

    var TestSlice = []float32 {.03, .02}
    var TestArray = [2]float32 {.03, .02}
    var TestArray2 = [...]float32 {.03, .02}
    

    [...] 告诉编译器计算数组本身的长度。切片包装数组并且在大多数情况下更容易使用。不要使用常量,只需使用小写首字母使其他包无法访问变量:

    var ThisIsPublic = [2]float32 {.03, .02}
    var thisIsPrivate = [2]float32 {.03, .02}
    

    thisIsPrivate 仅在它定义的包中可用。如果您需要从外部读取访问权限,您可以编写一个简单的 getter 函数(请参阅Getters in golang)。

    【讨论】:

      【解决方案3】:

      Go 中没有数组常量这种东西。

      引用Go Language Specification: Constants:

      布尔常量符文常量整数常量浮点常量复杂常量字符串常量。符文、整数、浮点数和复数常量统称为数值常量

      Constant expression(用于初始化常量)可能仅包含 constant 操作数,并在编译时进行评估。

      规范列出了不同类型的常量。请注意,您可以使用constant expressions 的类型创建和初始化常量,这些类型的允许类型之一为underlying type。例如这是有效的:

      func main() {
          type Myint int
          const i1 Myint = 1
          const i2 = Myint(2)
          fmt.Printf("%T %v\n", i1, i1)
          fmt.Printf("%T %v\n", i2, i2)
      }
      

      输出(在Go Playground 上试试):

      main.Myint 1
      main.Myint 2
      

      如果需要数组,只能是变量,不能是常量。

      我推荐这篇关于常量的精彩博客文章:Constants

      【讨论】:

      • 如果需要一个固定大小的容器怎么办?
      • @Atomic_alarm 你能详细说明一下吗?
      • 在golang类比C-array中是否存在?
      • @Atomic_alarm 是的,Go 中也确实存在数组,它们只是不是常量表达式,它们是在运行时计算的。所以常量不能是数组类型,但变量可以。例如:var arr = [2]int{2, 3}
      【解决方案4】:

      正如其他人所提到的,没有官方的 Go 构造。我能想象的最接近的是返回切片的函数。这样,您可以保证没有人会操纵原始切片的元素(因为它被“硬编码”到数组中)。

      我已经缩短了你的切片以使其...更短...:

      func GetLetterGoodness() []float32 {
          return []float32 { .0817,.0149,.0278,.0425,.1270,.0223 }
      }
      

      【讨论】:

      • 这听起来像是最好的方法,但是 func 返回类型不匹配。 cannot use [6]string literal (type [6]string) as type []string in return argument 所以return []float32 { ... }
      • @theRemix 三个可能的修复:(1) 删除 ... 以便声明切片文字而不是数组文字。 (2) 将返回类型改为[6]float32。 (3) 将表达式分配给数组变量a := [...]float32 { (etc.) },并返回所有元素的切片:return a[:]。 (数组文字不可寻址,我不清楚为什么。)
      • 我不确定你的保证是什么意思。听起来您尝试解决代码中的某些问题,而使用(单元)测试可能会更好地解决。
      猜你喜欢
      • 1970-01-01
      • 2013-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多