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  无法获取内存地址
}

数字常量不会被分配存储空间,无需像变量那样通过内存来取值,因此无法获取内存地址。

posted @   明王不动心  阅读(260)  评论(0编辑  收藏  举报
编辑推荐:
· 基于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
点击右上角即可分享
微信分享提示