Go语言中常量必须用const声明,不能用var;const声明的值编译期确定,支持iota枚举,无类型常量可自动推导类型,但不可为运行时结果。

Go语言中用 const 声明常量,不能用 var
Go 里常量必须用 const 关键字声明,和变量严格分离。写成 var PI = 3.14159 看似能运行,但实际是声明了一个变量,不是常量——它可被重新赋值、不参与编译期优化、无法用于数组长度等需要编译期确定值的场景。
正确写法是:
const PI = 3.14159 const MaxRetry = 3 const AppName = "myapp"
-
const声明的标识符默认可导出(首字母大写),如需包内私有,用小写开头:const defaultTimeout = 5000 - 类型可显式指定(
const Port int = 8080),也可省略由右值推导;但一旦指定,就不能赋值为其他类型(比如const Port int = 8080.0会报错) - 未显式指定类型的常量是“无类型常量”(untyped constant),在参与运算或赋值时按上下文自动转换,灵活性高,但也容易隐式溢出(比如
const Big = 1 在 32 位环境可能出问题)
批量声明常量用 const 块,注意 iota 的行为
多个相关常量建议用 const 块统一管理,尤其配合 iota 枚举。但 iota 不是“全局计数器”,它只在每个 const 块内从 0 开始、每行自增 1。
const (
StatusOK = iota // 0
StatusNotFound // 1
StatusServerError // 2
)- 某行想跳过自增?用下划线占位:
_ = iota或直接写_ - 想重置起始值?新开一个
const块,或用表达式重置:StartCode = iota + 100 -
iota只对“单行单常量”生效;如果一行声明多个(a, b = iota, iota),它们值相同,不会分别加 1
常量不能是运行时结果,比如 time.Now() 或函数返回值
Go 常量必须在编译期就能确定值。下面这些写法全部非法:
立即学习“go语言免费学习笔记(深入)”;
const now = time.Now() // ❌ time.Now() 是运行时调用
const len = len("hello") // ❌ len 是内置函数,但非编译期常量函数
const x = rand.Intn(10) // ❌ rand 是运行时库- 只有字面量(
42、"hello")、已定义常量、以及有限的编译期可计算表达式(如1 、2 + 3 * 4)才允许 - 字符串拼接可以用
+(const Path = "/api/" + "v1"合法),但不能含变量或函数调用 - 如果需要运行时“固定值”,只能用
var声明不可导出变量 + 初始化函数(如init()),但这不属于常量语义
常量常见误用:当数组长度、结构体字段默认值、HTTP 状态码别名
常量最核心价值是提供编译期确定性。典型合理用法包括:
- 数组/切片长度:
const BufferSize = 4096; var buf [BufferSize]byte—— 这样才能声明数组类型 - HTTP 状态码别名:
const StatusBadRequest = 400,比硬编码数字更易读且防错 - 配置阈值:
const MaxUploadSize = 10 ,避免魔法数字散落各处
但要注意:结构体字段不能设默认常量值(Go 不支持字段默认值语法),也不能把常量直接当 struct tag 值(tag 必须是字符串字面量,`json:"name"` 合法,`json:FieldName` 非法)。
最容易被忽略的是:无类型常量在跨包传递时,若接收方未显式指定类型,可能因平台差异(int 大小)或上下文推导导致意外截断或溢出,尤其是涉及位运算和大整数时。宁可多写 int64、uint32 显式标注。










