menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right All_wiki chevron_right the-way-to-go_ZH_CN chevron_right eBook chevron_right 04.3.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    04.3.md
    5.04 KB / 2024-07-16 23:14:27
        # 4.3 常量
    
    常量使用关键字 `const` 定义,用于存储不会改变的数据。
    
    存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
    
    常量的定义格式:`const identifier [type] = value`,例如: 
    
    ```go
    const Pi = 3.14159
    ```
    
    在 Go 语言中,你可以省略类型说明符 `[type]`,因为编译器可以根据变量的值来推断其类型。
    
    - 显式类型定义: `const b string = "abc"`
    - 隐式类型定义: `const b = "abc"`
    
    一个没有指定类型的常量被使用时,会根据其使用环境而推断出它所需要具备的类型。换句话说,未定义类型的常量会在必要时刻根据上下文来获得相关类型。
    
    ```go
    var n int
    f(n + 5) // 无类型的数字型常量 “5” 它的类型在这里变成了 int
    ```
    
    常量的值必须是能够在编译时就能够确定的;你可以在其赋值表达式中涉及计算过程,但是所有用于计算的值必须在编译期间就能获得。
    
    - 正确的做法:`const c1 = 2/3`  
    - 错误的做法:`const c2 = getNumber()` // 引发构建错误: `getNumber() used as value`
    
    **因为在编译期间自定义函数均属于未知,因此无法用于常量的赋值,但内置函数可以使用,如:`len()`。**
    
    数字型的常量是没有大小和符号的,并且可以使用任何精度而不会导致溢出:
    
    ```go
    const Ln2 = 0.693147180559945309417232121458\
    			176568075500134360255254120680009
    const Log2E = 1/Ln2 // this is a precise reciprocal
    const Billion = 1e9 // float constant
    const hardEight = (1 << 100) >> 97
    ```
    
    根据上面的例子我们可以看到,反斜杠 `\` 可以在常量表达式中作为多行的连接符使用。
    
    与各种类型的数字型变量相比,你无需担心常量之间的类型转换问题,因为它们都是非常理想的数字。
    
    不过需要注意的是,当常量赋值给一个精度过小的数字型变量时,可能会因为无法正确表达常量所代表的数值而导致溢出,这会在编译期间就引发错误。另外,常量也允许使用并行赋值的形式:
    
    ```go
    const beef, two, c = "eat", 2, "veg"
    const Monday, Tuesday, Wednesday, Thursday, Friday, Saturday = 1, 2, 3, 4, 5, 6
    const (
    	Monday, Tuesday, Wednesday = 1, 2, 3
    	Thursday, Friday, Saturday = 4, 5, 6
    )
    ```
    
    常量还可以用作枚举:
    
    ```go
    const (
    	Unknown = 0
    	Female = 1
    	Male = 2
    )
    ```
    
    现在,数字 `0`、`1` 和 `2` 分别代表未知性别、女性和男性。这些枚举值可以用于测试某个变量或常量的实际值,比如使用 switch/case 结构([第 5.3 节](./05.3.md))。
    
    在这个例子中,`iota` 可以被用作枚举值:
    
    ```go
    const (
    	a = iota
    	b = iota
    	c = iota
    )
    ```
    
    第一个 `iota` 等于 0,每当 `iota` 在新的一行被使用时,它的值都会自动加 1,并且没有赋值的常量默认会应用上一行的赋值表达式:
    
    ```go
    // 赋值一个常量时,之后没赋值的常量都会应用上一行的赋值表达式
    const (
    	a = iota  // a = 0
    	b         // b = 1
    	c         // c = 2
    	d = 5     // d = 5   
    	e         // e = 5
    )
    
    // 赋值两个常量,iota 只会增长一次,而不会因为使用了两次就增长两次
    const (
    	Apple, Banana = iota + 1, iota + 2 // Apple=1 Banana=2
    	Cherimoya, Durian                  // Cherimoya=2 Durian=3
    	Elderberry, Fig                    // Elderberry=3, Fig=4
    
    )
    
    // 使用 iota 结合 位运算 表示资源状态的使用案例
    const (
    	Open = 1 << iota  // 0001
    	Close             // 0010
    	Pending           // 0100
    )
    
    const (
    	_           = iota             // 使用 _ 忽略不需要的 iota
    	KB = 1 << (10 * iota)          // 1 << (10*1)
    	MB                             // 1 << (10*2)
    	GB                             // 1 << (10*3)
    	TB                             // 1 << (10*4)
    	PB                             // 1 << (10*5)
    	EB                             // 1 << (10*6)
    	ZB                             // 1 << (10*7)
    	YB                             // 1 << (10*8)
    )
    ```
    
    ( **译者注:关于 `iota` 的使用涉及到非常复杂多样的情况,这里作者解释的并不清晰,因为很难对 `iota` 的用法进行直观的文字描述。如希望进一步了解,请观看视频教程 [《Go编程基础》](https://github.com/Unknwon/go-fundamental-programming) [第四课:常量与运算符](https://github.com/Unknwon/go-fundamental-programming/blob/master/lectures/lecture4.md)** )
    
    `iota` 也可以用在表达式中,如:`iota + 50`。在每遇到一个新的常量块或单个常量声明时, `iota` 都会重置为 0( **简单地讲,每遇到一次 const 关键字,`iota` 就重置为 0** )。
    
    当然,常量之所以为常量就是恒定不变的量,因此我们无法在程序运行过程中修改它的值;如果你在代码中试图修改常量的值则会引发编译错误。
    
    
    ## 链接
    
    - [目录](directory.md)
    - 上一节:[Go 程序的基本结构和要素](04.2.md)
    - 下一节:[变量](04.4.md)
    
    
    links
    file_download