go中const必须带类型或初始值,不支持空声明;多常量块中iota继承易致类型混淆;const仅限编译期字面量,不可用运行时值初始化;字符串转[]byte会重复分配内存。

Go 里 const 声明必须带类型或初始值
不写类型也不给值,const x 直接报错:missing value in const declaration。Go 不允许“空常量”,哪怕后面用 const x = 5 这种推导形式,也得有等号右边的表达式。
常见错误是照搬其他语言习惯,比如想先声明再赋值,或者只写 const port 然后在别处初始化——这在 Go 里语法不通。
-
const port = 8080✅ 类型由字面量自动推导为int -
const timeout time.Duration = 30 * time.Second✅ 显式指定类型,避免跨包传参时类型不匹配 -
const version❌ 编译失败:缺少初始值
const 块中省略类型和值的写法(iota 的坑)
多个 const 写在一块时,第二行起可以省略类型和值,但前提是前一行有完整定义且用了 iota——否则容易误以为“自动继承”,结果类型悄悄变了。
比如下面这段看似简洁,实则危险:
const (
ModeTCP = iota
ModeUDP
ModeHTTP
)
它等价于 ModeTCP = 0, ModeUDP = 1, ModeHTTP = 2,全是 int。但如果你中间插了显式值:
const (
ModeTCP = iota
ModeUDP
ModeHTTP = "http" // ← 这里类型变成 string
ModeHTTPS // ← 这个会继承上一行的 string 类型,不是 int!
)
- 一旦块内出现非
iota表达式(比如字符串、浮点数),后续未显式赋值的常量会继承该类型 - 混用数值和字符串常量时,务必每行都写清楚类型,比如
ModeHTTP string = "http" -
iota只在当前 const 块有效,不同块之间不延续
const 不能用运行时变量初始化
const 是编译期确定的,所以不能用函数调用、全局变量、struct 字段甚至 len(os.Args) 这类东西初始化。常见错误是试图用 os.Getenv 或配置文件读取结果做 const。
-
const dbHost = os.Getenv("DB_HOST")❌ 编译失败:function call not allowed in constant expression -
const maxRetries = 3✅ 字面量,没问题 - 需要运行时值?改用
var,或者用init()函数预设
字符串 const 和 []byte 的零拷贝陷阱
定义字符串常量本身没性能问题,但很多人顺手把它转成 []byte 传给函数,比如 json.Unmarshal([]byte(MyJSON), &v)——每次调用都会分配新 slice,底层仍指向同一片只读内存,但逃逸分析可能把它当可变数据处理。
- 如果这个字符串很大且高频使用,建议提前转好:
var MyJSONBytes = []byte(MyJSON) - 更安全的做法是用
unsafe.String(Go 1.20+)或unsafe.Slice避免复制,但需确认目标 API 接受unsafe操作 - 注意:
const MyJSON = `{...}`是只读的,但[]byte(MyJSON)是新分配的,内容虽同,地址不同
类型推导、iota 继承规则、运行时约束、底层内存表现——这些地方不写注释、不查文档,很容易在重构或跨包调用时突然出问题。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











