我们编写了一个程序,通过它我们试图找到一个常量的地址。有可能这样做吗?
package main
func main() {
const k = 5
address := &k
}
它给出了一个错误,任何人都可以告诉我们如何找到常量的地址?
答案 0 :(得分:20)
简而言之:你不能。
错误消息显示:
不能取k的地址
地址运算符&
的操作数存在限制。 Spec: Address operators:
对于
x
类型的操作数T
,地址操作&x
生成*T
到x
类型的指针。操作数必须是可寻址,即变量,指针间接或切片索引操作;或可寻址结构操作数的字段选择器;或者可寻址数组的数组索引操作。作为可寻址性要求的例外,x
也可能是(可能带括号的)composite literal。如果对x
的评估会导致run-time panic,那么对&x
的评估也会如此。
常量不列为可寻址,未在规范中列为可寻址(上面引用)的内容不能是地址运算符&
的操作数(不能取其地址)。
不允许获取常量的地址。这有两个原因:
如果需要指向一个等于该常量的值的指针,请将其指定给一个可寻址的变量,这样就可以获取其地址,例如
func main() {
const k = 5
v := k
address := &v // This is allowed
}
但是要知道Go中的数字常量表示任意精度的值,不会溢出。当您将常量的值赋给变量时,可能无法实现(例如,常量可能大于您为其分配的变量类型的最大值 - 导致编译时错误),或者它可能不一样(例如,在浮点常数的情况下,它可能会失去精度)。
答案 1 :(得分:1)
在单元测试期间创建大型嵌套JSON对象时,我经常遇到此问题。我可能有一个结构,其中所有字段都是指向字符串/整数的指针:
type Obj struct {
Prop1 *string
Prop2 *int
Status *string
}
并且想要写类似的东西:
obj := Obj{
Prop1: &"a string property",
Prop2: &5,
Status: &statuses.Awesome,
}
当我初始化它时,但是语言不允许直接这样做。绕过此方法的一种快速方法是定义一个函数,该函数需要一个常量并返回其地址:
s := func(s string) *string { return &s }
i := func(s int) *int { return &i }
obj := Obj{
Prop1: s("a string property"),
Prop2: i(5),
Status: s(statuses.Awesome)
}
之所以可行,是因为当将常量作为参数传递给函数时,会复制该常量,这意味着在函数中创建的指针并不指向常量的地址,而是指向常量的地址。其副本的地址,与将常量值分配给var
时相同。但是,使用函数来执行此操作使IMO不必先声明大的变量块,而使IMO更具可读性/麻烦。
答案 2 :(得分:-3)
constants部分没有说清楚:与变量不同,常量不存在于编译代码或正在运行的程序中。它们是无类型,只有在分配给变量后才会在内存中。
结果,它们似乎 1 具有无限精度。如果你看一下this example,你可以看到我可以将常量分配给一个变量而不需要它,并且变量将保持尽可能多的常量精度。
1 正如spec也指出的那样,整数至少有256位,浮点数至少为256位尾数和32位指数,如果内部编译器将抛出错误构造不能准确存储常量。