Go 中 const 声明编译期常量,无内存地址、不可取址、不可赋值,编译时直接替换为字面量或求值结果;支持 const () 组合与 iota 枚举提升可维护性。

在 Go 语言中,const 关键字用于声明**编译期常量**,它确保值在程序运行期间完全不可变——不是“运行时不让改”,而是根本**没有内存地址、无法取地址、无法赋值覆盖**,从语言设计上杜绝修改可能。
const 的本质:编译期确定的不可变值
Go 的 const 不是变量加只读修饰,而是直接将标识符绑定到一个固定字面量或编译期可计算的表达式。例如:
const Pi = 3.14159 —— 编译后所有出现 Pi 的地方都会被替换成 3.14159,不占运行时内存;
const MaxRetry = 3 * 2 —— 表达式在编译时求值为 6,结果仍是常量。
这意味着:
- 不能对 const 取地址(&Pi 报错)
- 不能用 := 或 = 重新赋值
- 不能传给需要指针或可寻址参数的函数(除非显式转换为变量)
定义常量组提升可维护性
多个相关常量建议用 const () 块统一管理,支持隐式重复和 iota 枚举:
立即学习“go语言免费学习笔记(深入)”;
const (
StatusOK = 200
StatusNotFound = 404
StatusInternalServerError = 500
)
更简洁写法(利用隐式重复):
const (
StatusOK = 200
StatusNotFound
StatusInternalServerError
)
此时后两项自动继承前一项的值(即都为 200),通常配合 iota 更实用:
const (
ModeRead = 1
ModeWrite // 2
ModeExecute // 4
)
区分 const 和 var + unexported field
如果目标是“结构体字段不可外部修改”,const 无法用于字段(字段必须是变量)。此时应结合封装:
- 字段小写(如
name string),不导出 - 只提供 getter 方法(如
func (u User) Name() string { return u.name }) - 不提供 setter,或 setter 内做校验/仅初始化期允许赋值
这属于运行时逻辑保护,和 const 的编译期不可变有本质区别。
注意:const 不能替代配置或运行时参数
以下场景 不能用 const:
- 从环境变量、配置文件读取的值(如数据库地址)
- 启动时动态生成的密钥或 token
- 用户输入或 API 返回的固定值(即使当前不变,未来可能变)
这些应使用 var 声明变量,并通过构造函数、依赖注入或配置中心管理,必要时用 sync.Once 或只读接口约束访问。










