Files
cs-note/hzh/GolangStar/Go语言基础/Go语言常量.md
T

130 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [go, golang, go基础语法, 常量]
create time: 2026-06-07 15:00
---
# Go 语言常量
## 概述
常量是编译期确定的不可变值。本文介绍常量的声明方式、`iota` 枚举技巧,以及常量与变量的关键区别。
## 正文
### 常量 vs 变量:本质区别是什么?
**常量在编译期就确定了值,之后不可修改。** 这意味着编译器可以做更多优化,比如内联替换、死代码消除等。
```go
const MaxSize = 1024 // 编译期确定,不可更改
// MaxSize = 2048 // ❌ 编译错误:cannot assign to MaxSize
var BufferSize = 1024 // 运行时可变
BufferSize = 2048 // ✅ 合法
```
> [!note] 📝 常量类型限制
> 只能是布尔型、数字型(整数/浮点/复数)、字符串。不能是 slice、map、struct 等复杂类型。
### 声明方式
```go
const name type = value // 显式类型
const name = value // 类型推断(更常用)
// 多常量一行声明
const a, b = "hello", "world"
```
### `iota`:Go 的枚举神器
`iota` 是 Go 最优雅的枚举机制之一——它是 `const` 块内的**行索引**,从 0 开始,每行自动 +1。
```go
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
```
> [!tip] 💡 省略写法
> 同一 `const` 块内,如果后续行的值和上一行一样(都是 `iota`),可以省略右侧表达式:
```go
const (
Sunday = iota // 0
Monday // 1 ← 自动继承 iota
Tuesday // 2
)
```
#### `iota` 的高级用法
当某行出现了**非 iota 的独立值**后,`iota` 继续计数,但其他常量需要重新指定表达式:
```go
const (
a = iota // 0
b // 1
c // 2
d = "ha" // "ha" — 独立值,iota 变成 3
e // "ha" — 继承上一行的值,iota 变成 4
f = 100 // 100 — 独立值,iota 变成 5
g // 100 — 继承,iota 变成 6
h = iota // 6 — 恢复计数
i // 7
)
```
#### 位运算枚举
结合位移操作,`iota` 可以优雅地生成幂次值:
```go
const (
_ = iota // 0,用 _ 丢弃
KB = 1 << (10 * iota) // 1 << 0 = 1(通常不用)
MB // 1 << 10 = 1024
GB // 1 << 20 = 1048576
TB // 1 << 30 = 1073741824
)
```
> [!question] ❓ 思考
> 上面这段代码中,`KB`、`MB`、`GB` 的值分别是多少?为什么 `_` 那行很重要?
### 常量可以用在编译期函数中
`len()`、`cap()`、`unsafe.Sizeof()` 等在常量上下文中是**编译期求值**的:
```go
const s = "abc"
const n = len(s) // n == 3,编译期确定
const sz = unsafe.Sizeof(s) // sz == 16(string struct 大小)
```
> [!info] ℹ️ 为什么 `sizeof("abc")` 是 16?
> Go 的 `string` 底层是一个结构体:`{ptr *byte, len int}`,两个字段各占 8 字节(64 位平台),所以 `unsafe.Sizeof(string)` 恒为 16。它不包含字符串的实际内容,只包含指向内容的指针和长度。
### 常量分组示例(枚举最佳实践)
```go
type StatusCode int
const (
OK StatusCode = 200
NotFound StatusCode = 404
ServerError StatusCode = 500
)
```
给枚举值绑定自定义类型(如 `StatusCode`)可以提供类型安全——不同枚举类型之间不能直接比较。
> [!warning] ⚠️ 常见陷阱
> 不带类型的裸 `const` 会隐式转换为 `int`。如果需要类型安全,务必显式声明类型或先定义枚举类型。