Go 中 const 值没有内存地址,因其在编译期被直接替换为字面值,不分配运行时内存,故无法取地址,任何 &constValue 都会触发编译错误;需用 var 声明变量后取址。
Go 中
值没有内存地址
因为
在编译期就被替换成字面值,不分配运行时内存。Go 编译器会把所有对常量的引用直接内联为对应值(比如
,后续写
时,编译器根本找不到一个“变量”来取地址)。
这和 C/C++ 不同:C 的
变量仍占内存(只是加了只读修饰),而 Go 的
是纯编译期符号,连符号表里都不一定保留。
会直接报错
尝试对任何
取地址都会触发
编译错误
,无论类型是
、
还是自定义类型:
常见误操作场景:
立即学习
“
go语言免费学习笔记(深入)
”;
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
想传指针给函数(比如
)→ 改用
(先赋值给变量)
初始化结构体字段为指针(
)→ 必须先声明变量:
在切片或 map 中存常量地址 → 不可行,需用变量兜底
替代方案:用变量包装常量再取地址
如果确实需要指针,唯一合法方式是用
显式声明变量,并初始化为该常量:
注意点:
不能写成
然后立即取地址——必须分两步或确保变量已分配空间
短变量声明
也有效:
这种变量不会被编译器优化掉,哪怕值和常量完全一样
为什么设计成这样?性能与语义一致性
Go 把常量视为“值本身”,不是“可寻址实体”。这种设计带来两个实际好处:
避免对字面值取地址引发的歧义(比如
或
在其他语言中行为不一)
让编译器能更激进地做常量折叠和内联,减少不必要的内存分配
强制开发者区分“不可变值”(
)和“只读存储位置”(
初始化)
真正容易被忽略的是:哪怕常量类型实现了接口,也不能直接取地址转为接口指针——必须经过变量中转。这点在写泛型约束或反射逻辑时特别容易踩坑。
constconstconst pi = 3.14159&piconstconst&constValuecannot take the address of ...constintstringconst name = "gopher"
ptr := &name // 编译错误:cannot take the address of namefmt.Printf("%s", &name)&tempConfig{Title: &name}title := name; Config{Title: &title}varconst mode = 0644
var modeVar = mode
permPtr := &modeVar // ✅ 合法var modeVar = constValue:=modeVar := mode; ptr := &modeVar&42&"hello"constvar + const