Go 语言编程 — 变量与常量

忘是亡心i 2023-10-06 12:25 170阅读 0赞

目录

文章目录

  • 目录
  • 值语义和引用语义
  • 变量(var)
    • 变量声明:显式指定数据类型
    • 变量声明与定义:根据初始化数值自动判定数据类型
    • 变量声明与定义:短声明,使用 := 海象运算符
    • 同时声明多个变量
  • 常量(const)
    • 使用 iota 常量来实现 “枚举类型”

值语义和引用语义

在 C 语言中,所有变量都是值语义的。变量名所指向的内存位置,就是变量值所储存的地方。指针变量亦如此,指针变量名所指向的内存位置,就是储存指针变量值(一个内存地址)的地方。

在 Python 中,所有变量都是引用语义的。变量名所指向的内存位置所存储的内容,实际上是变量值在内存中的地址。

而 Golang 则显式的值语义和引用语义都引入了程序设计中,布尔型、数字类型、字符串类型都属于值语义,变量名指向变量值。当使用 = 赋值运算符将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将变量 i 的数值进行了拷贝:

在这里插入图片描述

而 Golang 中更复杂的数据类型通常使用引用语义。一个引用类型的变量 r1 存储的是 r1 的值所在的内存地址,或内存地址中的首地址。当使用赋值语句 r2 = r1 时,只有引用(地址)被复制,如果 r1 的值被改变了,那么这个值的所有引用都会指向被修改后的内容,在这个例子中,r2 也会受到影响:

在这里插入图片描述

变量(var)

Golang 使用关键字 var 来声明一个变量。格式如下:

  1. var identifier type

也可以一次声明多个变量,称为 “并行赋值”,也可用于接受多返回值函数的返回值:

  1. var identifier1, identifier2 type

声明全局变量:

  1. // 这种因式分解关键字的写法一般用于声明全局变量
  2. var (
  3. identifier1 type
  4. identifier2 type
  5. )

注意

  1. 不可以在同一个代码块中重复声明一个同名变量。
  2. 在函数块中,不可以仅声明,但不可以一个变量。
  3. 全局变量是可以仅声明,而不使用的。
  4. 并行赋值时,可以在赋值运算符的左侧使用空白标识符 “_”,表示抛弃值,常用接受多返回值的函数调用,进行对齐补位。空白标识符的本质是一个只写(wo)变量,你不能得到它的值。这样做是因为 Golang 中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数返回中得到的所有返回值。

变量声明:显式指定数据类型

与 C 语言一般,可以在一条语句中完成变量的声明、定义以及初始化。如果没有初始化,则变量默认为零值。

示例:

  1. package main
  2. import "fmt"
  3. func main() {
  4. var num int
  5. fmt.Println(num)
  6. var name string = "fanguiju"
  7. fmt.Println(name)
  8. }

注意,不同数据类型的零值亦不相同。例如:布尔类型的零值为 false,数值类型的零值为 0,字符串的零值为空(””),以下几种类型为 nil:

  1. var a *int // 声明指针变量
  2. var a []int // 声明数组变量
  3. var a map[string]int // 声明 Map 变量
  4. var a chan int // 声明 channel 变量
  5. var a func(string) int // 声明函数变量,类型为 func(string)
  6. var a error // 声明 error 接口变量

变量声明与定义:根据初始化数值自动判定数据类型

示例:

  1. package main
  2. import "fmt"
  3. func main() {
  4. // var a bool = true
  5. var b = true
  6. fmt.Println(b)
  7. }

变量声明与定义:短声明,使用 := 海象运算符

上述可知,Golang 支持在初始化变量的时候省略显式书写数据类型。基于这样的前提,声明语句写上 var 关键字就显得有些多余了。所以,Golang 可以使用 := 赋值运算符来省略书写 var 关键字和数据类型的预定义标识符,是一种简易的写法,通过初始化的数值来确定变量的数据类型。

注意,:= 运算法的简短形式只能在函数中使用,否则编译错误。

示例:

  1. package main
  2. import "fmt"
  3. func main() {
  4. f := "fanguiju" // 相对于:var f string = "fanguiju"
  5. fmt.Println(f)
  6. }

但需要注意的是,:= 运算符的左值必须是新声明的变量。不能使用 := 来为已经声明或定义过的变量进行赋值,会导致编译错误。

  1. var intVal int
  2. intVal := 1 // 编译错误

同时声明多个变量

例如:

  1. var vname1, vname2, vname3 string = "A", "B", "C"
  2. // or
  3. var vname1, vname2, vname3 = "A", "B", "C"
  4. // or
  5. vname1, vname2, vname3 := "A", "B", "C"

常量(const)

Golang 中使用 const 关键字来声明常量,常量的数据类型只可以是:布尔类型、数字类型和字符串类型。

声明格式:

  1. const identifier type = value

与变量声明类似的,可以省略显式书写数据类型:

  1. const b = "abc"

也可以进行并行赋值:

  1. const c_name1, c_name2 = value1, value2

注意,定义常量不能使用 := 运算符。

Golang 内置的标准函数中:len()、cap()、unsafe.Sizeof() 返回的都是一个常量,所以应该直接赋值与一个常量:

  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. // 批量声明定义常量对象
  7. const (
  8. a = "abc"
  9. b = len(a)
  10. c = unsafe.Sizeof(a)
  11. )
  12. func main() {
  13. fmt.Println(a, b, c)
  14. }

结果:

  1. abc 3 16

使用 iota 常量来实现 “枚举类型”

Golang 原生不具备 C 语言中的枚举类型关键字 enum,但可以使用 const 关键字和 iota 常量来实现。

通常的,使用因式分解的方式声明多个常量时,后一个常量成员会继承前一个常量成员的数值(若前一个成员有初始化,后一个成员没有初始化的情况下),如下:

  1. package main
  2. import "fmt"
  3. const (
  4. Unknown = 1
  5. Female
  6. Male
  7. )
  8. func main() {
  9. fmt.Println(Unknown, Female, Male)
  10. }

结果:

  1. 1 1 1

iota(希腊字母艾欧他,对应拉丁字母 i)表示下标,是一个特殊的常量,其数值可以被编译器所修改。iota 结合上述的 const 隐性重复最后一个非空表达式的语法糖,可以用于递增场景(常量生成器)。

iota 在 const 关键字出现时会被重置为 0,批量创建常量时,在同一 “批” 中,每新增一行常量声明,就会使 iota 计数一次。所以,iota 的本质可理解为 const 语句块中的行索引。

  1. package main
  2. import "fmt"
  3. const (
  4. a = iota
  5. b = iota
  6. c = iota
  7. )
  8. /* 也可以简写为如下形式:
  9. *
  10. * const (
  11. * a = iota
  12. * b
  13. * c
  14. * )
  15. */
  16. func main() {
  17. fmt.Println(a, b, c)
  18. }

结果:

  1. 0 1 2

示例:

  1. package main
  2. import "fmt"
  3. const (
  4. a = iota // 0
  5. b // 1
  6. c // 2
  7. d = "ha" // 独立值,iota += 1
  8. e // 继承上一个值,iota += 1
  9. f = 100 // 独立值,iota +=1
  10. g // 继承上一个值,iota +=1
  11. h = iota // 7(恢复计数)
  12. i // 8
  13. )
  14. func main() {
  15. fmt.Println(a, b, c, d, e, f, g, h, i)
  16. }

运行结果:

  1. 0 1 2 ha ha 100 100 7 8

再看个有趣的的 iota 示例:

  1. package main
  2. import "fmt"
  3. const (
  4. i = 1 << iota // 位左移运算符 1 位
  5. j = 3 << iota // 位左移运算符 2 位
  6. k // 位左移运算符 3 位
  7. l // 位左移运算符 4 位
  8. )
  9. func main() {
  10. fmt.Println("i=", i)
  11. fmt.Println("j=", j)
  12. fmt.Println("k=", k)
  13. fmt.Println("l=", l)
  14. }

结果:

  1. i= 1
  2. j= 6
  3. k= 12
  4. l= 24

简单表述:

  • i = 1 << iota:iota 为 0,左移 0 位,二进制 001,不变,仍为 1;
  • j = 3 << iota:iota 为 1,左移 1 位,二进制 110,即 6;
  • k = 3 << iota:iota 为 2,左移 2 位,二进制 1100,即 12;
  • l = 3 << iota:iota 为 3,左移 3 位,二进制 11000,即 24。

发表评论

表情:
评论列表 (有 0 条评论,170人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Go——变量常量

    1、变量 变量:使用一个名称来绑定一块内存地址,该内存地址中存放的数据类型由定义变量时指定的类型决定,该内存地址里面存放的内容可以改变。 1.1 显示的完整声明

    相关 Go语言基础】变量常量

    用Go语言编写的程序都是从基本组件构成,而构成这些基本组件的是标识符,本章中将介绍到Go语言中使用到变量,常量以及基本数据类型。 1. 标识符 标识符是函数、变量、常量

    相关 Go语言笔记--常量运算符

    1.常量的定义 1)常量的值再编译时就已经确定 2)常量的定义格式与变量基本相同 3)等号右侧必须是常量或者常量表达式 4)常量表达式中的函数必须是内置函数 例如