声明一个常量数组


164

我努力了:

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数组?

Answers:


232

数组并不是天生不变的。您无法使其保持恒定。

您可以获得的最接近的是:

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 }

请注意[...]而不是[]:它可确保获得(固定大小)数组而不是切片。因此值不是固定的,但大小是固定的。


126
仅作说明:[...]T语法为[123]T。它创建一个固定大小的数组,但让编译器确定其中有多少个元素。
12

5
我猜想允许常量数组将需要更新类型系统。否则,如果您定义了一个函数,f(xs [5]int)您将不知道所传递的数组是常量还是可变的。
Thomas Ahle 2014年

韩国社交协会,我有问题,当我尝试strings.Join cannot use constants.FilesRequired (type [4]string) as type []string in argument to strings.Join
埃迪·埃尔南德斯

感谢您的切片解决方案。怀疑:数组本身是不可变的,对吗?创建数组后就无法添加或删除元素,不是吗?但是,我可以编辑数组元素。
legends2k

@ legends2k是的,您不能更改数组的大小,但是可以在其插槽中放置其他值。
DenysSéguret17年

63

有效出发:

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函数(请参阅golang中的Getters)。


12

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

引用Go语言规范:常量

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

常量表达式(这被用来初始化一个常数)可以仅含有恒定操作数和在编译时被评估。

该规范列出了不同类型的常量。请注意,可以使用具有允许的类型之一作为基础类型的类型的常量表达式来创建和初始化常量。例如,这是有效的:

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

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

我推荐这篇关于常量的出色博客文章:常量


那么,如果需要一个尺寸不变的容器怎么办?

@Atomic_alarm请详细说明吗?
icza 2015年

是否存在于golang模拟C阵列中?

@Atomic_alarm是的,Go中也确实存在数组,它们不是常量表达式,而是在运行时求值的。因此,常量不能是数组类型,而变量可以。例如:var arr = [2]int{2, 3}
icza

3

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

我已经缩短了切片,使其更短...:

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

4
这听起来是最好的方法,但是func返回类型不匹配。cannot use [6]string literal (type [6]string) as type []string in return argument所以return []float32 { ... }
theRemix

@theRemix三种可能的修复方法:(1)删除...以便声明切片文字而不是数组文字。(2)将返回类型更改为[6]float32。(3)将表达式分配给数组变量,a := [...]float32 { (etc.) }然后返回所有元素的切片:return a[:]。(数组字面量不可寻址,原因尚不清楚。)
David Moles

我不确定您能保证什么。听起来您尝试解决代码中的某些问题,而这些问题可能可以通过(单元测试)更好地解决。
Dynom
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.