02、常量

一、常量核心特性

常量是指编译期间就己知,且在执行过程中不会改变的固定值。在Go 语言程序中,常量可定义为数值(整型、浮点型和复数类型)、布尔值或字符串等类型。 常量使用关键宇const 定义,常量的定义格式:const identifier [type] = value

1. 编译期确定值

常量在编译阶段求值,运行时不会再计算;

不能用变量、自定义函数结果赋值常量,仅内置编译期函数(len/cap/real等)可用。

var a = 10
const b = a // 报错,变量运行期才有值
const c = len("123") // 合法,len编译期可算

2. 定义后不可修改

常量一经声明,全程只读,任何重新赋值都会编译报错。

const x = 5
x = 10 // 编译错误

3. 不占用堆 / 栈内存

编译时直接把常量值替换到代码对应位置,无内存分配;变量会分配内存存储。

4. 分无类型常量、有类型常量

无类型(默认,推荐)

不指定类型,适配多种数值类型,精度更高:

const num = 100
var i int8 = num
var f float64 = num

有类型常量

绑定固定类型,赋值只能匹配同类型:

const num int = 100
var i int8 = num // 类型不匹配报错

5.支持常量表达式运算

常量之间可做加减乘除、位运算、移位,全部编译期计算:

const PI = 3.14
const TwoPI = 2 * PI
const Flag = 1 << 3

6. 常量组 + iota 自增特性

  1. const() 分组批量定义,省略赋值会复用上行表达式;

  2. iota 是组内内置计数器,每组从 0 开始,每行 + 1;

  3. 新建 const 块,iota 重置为 0。

   const (
    A = iota // 0
    B        // 1
    C        // 2
)

7. 支持基础数据类型

仅支持布尔、数字(int/float/complex)、字符串、字符;

不支持数组、切片、map、结构体、指针等引用 / 复合类型

const s = "abc"
const ok = true
const n = 3.14
const arr = [2]int{1,2} // 报错,复合类型不能做常量

8. 作用域规则同变量

包级常量全局可用,函数内常量仅函数内部生效。

9. 无类型常量高精度

无类型浮点 / 整型常量精度远超普通变量,计算不易溢出;

一旦显式指定类型,就受该类型数值范围约束。

二、常量完整用法

一、基础定义

常量 const 是编译期确定、运行不可修改的值,支持数值、字符串、布尔、字符,不能是变量、函数返回值(除内置基础函数)。

单个常量

const PI = 3.1415
const Name string = "golang" // 显式指定类型
const Flag = true

批量常量(推荐)

const (
    A = 1
    B = 2
    C = "test"
)

二、iota 自增枚举(Go 核心特性)

iota 是常量组内置计数器,每行自动 + 1,初始值 0。

基础自增

const (
    a = iota // 0
    b        // 1(省略赋值,继承上一行表达式)
    c        // 2
)
// 订单状态枚举
	const (
		OrderPending   = iota // 待支付
		OrderPaid             // 已支付
		OrderShipped          // 已发货
		OrderCompleted        // 已完成
	)
	fmt.Println("订单状态枚举:", OrderPending, OrderPaid, OrderShipped, OrderCompleted) // 输出:0 1 2 3
/*
	常量不能用变量赋值
	iota 只在当前 const 块生效
	常量不能取地址
*/

位运算常用(枚举状态、权限)

const (
    Read = 1 << iota // 1 << 0 = 1*2⁰ = 1 0001
    Write            // 1 << 1 = 1*2¹ = 2 0010
    Exec             // 1 << 2 = 1*2² = 4 0100
)
    perm := Read | Write
	fmt.Println("组合读写权限:", perm) // 0011, 3

	perm |= Exec
	fmt.Println("添加执行权限:", perm) // 0111, 7

	if perm&Read != 0 {
		fmt.Println("有读权限") // 0111 & 0001 = 0001判断是否有读权限
	}

	perm &^= Write
	fmt.Println("移除写权限:", perm) // 0111 & ^0010 = 0111 & 1101 = 0101, 5

	/*
		x & Flag:检查有没有这个标记
		x | Flag:添加标记
		x &^ Flag:取反删掉这个标记
	*/

自定义步长 / 公式

const (
    _  = iota       // 跳过0
    X2 = iota * 2   // 1*2=2
    X4 = iota * 2   // 2*2=4
)

多常量一行,iota 只自增一次

const (
    m, n = iota, iota + 1 // 0,1
    p, q                  // 1,2
)

三、常量 vs 变量对比

特性const 常量var 变量
求值时机编译期运行期
是否可修改不可修改可重新赋值
内存分配无内存(直接替换值)分配内存
支持 iota支持不支持