go——常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量
常量中的数据类型只可以是布尔值、数字型(整数型、浮点型和复数)和字符串。
常量的定义格式:
1 | const identifier [ type ] = value |
你可以省略类型说明符[type],因为编译器可以根据变量的值来推断其类型。
显式定义:
1 | const b string = “abc” |
隐式定义:
1 | const b = “abc” |
多个相同类型的声明可以简写为:
1 | const c_name1,c_name2 = value1,value2 |
下面是一个综合示例:
1 | package main<br><br> const x int = 100 //显式定义<br>const y = false //隐式定义<br>const m, n = 111, 222 //一次定义多个,前提条件是类型一致<br><br>func main() {<br> const ( //以组的方式批量定义<br> i, f = 0, 1<br> b = false<br> )<br>} |
需要说明的是定义常量但是不使用常量并不会报错。
如果显式定义常量,必须保证常量左右两边的类型必须一致,需要的时候可以做显式转化。
同时,右值不能超出常量类型取值范围,否则会引发溢出错误。
1 | const k uint8 = 999 //constant 999 overflows uint8,uint8的最大取值是255 |
常量也可以是某些编译器能计算出结果的表达式。
1 2 3 4 | const ( ptrSize = unsafe.Sizeof(uintptr(0)) strSize = len( "hello, world" ) ) |
在常量组中如不指定类型和初始化值,则与上一行非空常量右值相同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package main import "fmt" func main() { const ( x int = 18 y //与上一行x类型和值相同 z = "abc" s ) fmt.Printf( "%T, %v\n" , y, y) fmt.Printf( "%T, %v\n" , s, s) } /* 结果: int, 18 string, abc */ |
iota
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
iota在const关键字出现时将被重置为0(const内部的第一行之前),
const中每新增一行常量声明将使iota计数一次(iota可以理解为const语句块中的行索引。)
1 2 3 4 5 | const ( a = iota b = iota c = iota ) |
第一个iota等于0,每当iota在新的一行被使用时,它的值都会自动加1,所以a=0,b=1,c=2,
可以简写为如下形式:
1 2 3 4 5 | const ( a = iota b c ) |
看几个简单的例子:
示例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package main import "fmt" const ( _ = iota kb = 1 << (10 * iota) mb gb ) /* gb和mb的值与kb的值相同 (kb = 1) << (10 * 1) 1 * 2**10 = 1024 (mb = 1) << (10 * 2) 1 * 2**20 = 1048576 (gb = 1) << (10 * 3) 1 * 2**30 = 1073741824 */ //iota值是自增的,向左移动n位,就是乘以2的n次方 func main() { fmt.Println(kb, mb, gb) } /* 结果: 1024 1048576 1073741824 */ |
示例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "hello" //重新赋值,但是iota +=1 e //引用上面,但是iota +=1 f = 100 //重新赋值 g h = iota //7 如果中断iota自增,必须显式恢复 i //8 ) fmt.Println(a, b, c, d, e, f, g, h, i) } //a, b, c, d, e, f, g, h, i //0 1 2 hello hello 100 100 7 8 |
常量与变量本质的差别
不同于变量在运行期间分配存储内存,常量通常会被编译器在预处理阶段直接展开,作为指令数据使用
1 2 3 4 5 6 7 8 9 10 11 12 | package main import "fmt" var x = 0x100 const y = 0x200 func main() { fmt.Println(&x, x) fmt.Println(&y, y) //cannot take the address of y 无法获取内存地址 } |
数字常量不会被分配存储空间,无需像变量那样通过内存来取值,因此无法获取内存地址。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2017-12-08 MySQL的information_schema库
2017-12-08 mysql复制表结构和内容
2017-12-08 第8条:不要使用含有两个以上表达式的列表推导
2017-12-08 第7条:用列表推导式来取代map和filter