四、Go语法基础(常量和变量)

55 阅读4分钟

Golang中文学习文档地址

1、常量

1.1 常量简介

  • 常量:常量一旦被赋值,在整个程序运行的生命周内,值都不允许被修改。

  • Go常量的来源:

    • 字面量
    • 其他常量标识符
    • 常量表达式
    • 结果是常量的类型转换
    • iota
  • 常量的类型只能是基本类型,不能是除基本类型外的所有类型,如:结构体、切片、数组等,也不能是函数的返回值

1.2 常量初始化

  • 常量使用const关键字声明,在声明时,常量必须初始化值。
const name = "zhangsan"
const num = 3
  • 常量的批量声明
const (
	Name = "zhangsan"
    Num = 3
)
  • 在同一组内的常量,如果常量值一样,除第一个常量外,剩余的不用赋值。
const (
    A = 1
    B //1
    C //1
    D //1	
)

1.3 iota

  • iota是一个内置的常量标识符,通常用于表示一个常量声明中的无类型整数序数,一般都是在批量声明的括号中使用。
const (
    A = iota //0
    B //1
    C //2
    D //3
)
const (
    A = iota * 2 //0
    B //2
    C //4
    D //6
)
  • 使用了匿名标识符_占了一行的位置,可以看到iota的值本质上就是iota所在行相对于当前const分组的第一行的差值。而不同的const分组则相互不会影响。
const (
	A = iota //0
	B //1
	C //2
	_ //3
	D //4
)

1.4 枚举

  • 在Go中没有enum关键字来定义枚举,一般是通过自定义类型 + const + iota来实现枚举。

    • 自定义类型 + const + iota
    //自定义季节类型
    type Season uint8
    // iota给常量赋值
    const (
      Spring Season = iota
      Summer
      Autumn
      Winter
    )
    
    • 给自定义类型绑定方法,获取枚举对应的字符串
    func (s Season) String() string {
      switch s {
      case Spring:
        return "spring"
      case Summer:
        return "summer"
      case Autumn:
        return "autumn"
      case Winter:
        return "winter"
      }
      return ""
    }
    

2、变量

2.1 变量简介

  • 变量是用于存储值的位置,并且变量允许是运行过程中动态变更(和常量的区别,常量不允许变更),变量定义好之后,会给变量分配一个内存,用于存储值。

2.2 变量的声明

  • Go中变量使用关键字var定义,与Java不同的是,Go变量类型是后置的,也就是先定义变量名称,再定义变量类型。
var num int //num:变量名 int:变量类型
var str string //stri:变量名 string:变量类型
  • 声明多个相同类型的变量
var num1,num2,num3 int //只需要一次变量类型
  • 声明多个不同类型的变量,可以使用()
var (
    num int
    str string
)
  • 变量只声明,而不做赋值,变量默认值就是声明类型的零值。

2.3 变量的赋值

  • 变量的赋值使用=符号。
var num int
num = 1
//可以在声明时直接赋值
var str string = "go" 

var name string
var age int
name,age = "golong",100 //可以多个变量一起赋值
  • 短变量初始化(:=),可省略var关键字和后置类型,由编译器自动推断类型。

    num := 2

    • 短变量初始化无法对一个已经赋值的变量进行变更,有一种情况除外,多变量一起赋值时,有一个新声明的变量。
    var num = 2
    num := 3 //编译器编译无法不通过
    num,age := 4,23 //因age是新声明的变量,所以允许该操作
    
    • 短变量初始化只能在函数内部使用,函数外部还是只能var关键字

2.4 变量的匿名

  • 当一个变量不需要使用时,可以使用_代替该变量。
// Open函数返回两个变量,当第二个变量后续无需使用时,可以用_替代,避免变量未使用导致编译无法通过。
file, _ := os.Open("readme.txt")

2.5 变量的交换

  • Go中,交换两个变量的值,可以直接使用赋值运算符直接进行交换。
num1,num2 := 1,2
num1,num2 = num2,num1
  • 变量的交换是先计算,再做交换的。
a, b, c := 0, 1, 1
a, b, c = b, c, a+b // a + b = 0 + 1,而不是1+1
//结果为 1,1,1

2.6 变量的比较

  • 变量的比较有一个大前提,就是要做比较的两个变量类型必须是同一类型。

  • Go中不存在隐式类型转换。

  • 内置的min和max函数,go1.21版本之后,这两个函数用泛型重写,支持了其他类型的比较(原先只支持浮点型)

    • 布尔
    • 数字
    • 字符串
    • 指针
    • 通道 (仅支持判断是否相等)
    • 元素是可比较类型的数组(切片不可比较)(仅支持判断是否相等)(仅支持相同长度的数组间的比较,因为数组长度也是类型的一部分,而不同类型不可比较)
    • 字段类型都是可比较类型的结构体(仅支持判断是否相等)
  • 标准库cmp,不过仅支持有序类型的参数,在 go 中内置的有序类型只有数字和字符串

import "cmp"

func main() {
  cmp.Compare(1, 2)
  cmp.Less(1, 2)
}

2.7 代码块

  • 在函数内部,可以通过花括号建立一个代码块,每个代码块内,变量作用域是相互独立的。
func main() {
  a := 1
  {
    a := 2
    fmt.Println(a)
  }
  {
    a := 3
    fmt.Println(a)
  }
  fmt.Println(a)
}