Skip to content

1-基础

标识符

  • [ _ | A-Z | a-z | 0-9 ]
  • 不能数字开头
  • 不能与关键字和保留字冲突

关键字

Go 中有25个关键字

1
2
3
4
5
    break        default      func         interface    select
    case         defer        go           map          struct
    chan         else         goto         package      switch
    const        fallthrough  if           range        type
    continue     for          import       return       var

37个保留字

Constants:  true  false  iota  nil

    Types:  int  int8  int16  int32  int64
            uint  uint8  uint16  uint32  uint64  uintptr
            float32  float64  complex128  complex64
            bool  byte  rune  string  error

Functions:  make  len  cap  new  append  copy  close  delete
                complex  real  imag
                panic  recover

变量

声明

var 变量名 变量类型

变量声明以关键字 var 开头,类型放在后面,无需分号

1
2
3
var name string
var age int
var isEmpty bool

批量声明

每个变量写一个 var 太麻烦,go 支持批量声明

1
2
3
4
5
6
7
var (
    name string
    age int
    isEmpty bool
)

var num1, num2, num3 int

初始化

Note

go 声明变量时,会自动对变量对应的内存区域进行初始化,每个变量都会被初始化成默认值。

eg:整型和浮点型变量默认值是 0,字符串变量默认值是 空字符串,布尔类型变量默认值是false,切片、函数、指针变量默认是 nil

同时,我们可以在声明变量时为其指定初始值,格式如下:

var 变量名 类型 = 表达式

eg:

var name string = "Boii"
var age  int    = 18

或者一次初始化多个变量。eg:

var name, age = "Boii", 18

Tip

Go 语言具有的这种特性,使得交换两个变量非常方便,可以简单地使用 a, b = b, a 完成交换两个变量的值。

类型推导

类型推导指的是 没有显示的写明类型,编译器会通过等号右边的值来推导出类型,然后完成初始化工作。

1
2
3
var name = "Boii"
var age = 18
height := 180

交换变量

1
2
3
a, b := 10, 15
a, b = b, a
fmt.Println(a, b)    // 15 10

短变量声明

在函数内部,可以用更简略的方式 := 声明并初始化变量,但这种方式**只能声明局部变量**

package main

import "fmt"

var m = 100    // 声明全局变量 m

func main() {
    n := 10    // 声明局部变量 n
    m := 200   // 声明局部变量 m
    fmt.Println(m ,n)
}

// ----------------------------------------
// Output:
200 10

匿名变量

使用多重赋值时,想要忽略某个值,可以使用 匿名变量,也就是一个下划线 _ 表示。eg:

func foo() (int, string) {
    return 18, "Boii"
}

func main() {
    x, _ := foo()
    fmt.Println("x =", x)
}
// ----------------------------------------
// Output:
18

匿名变量不占用命名空间,不会分配内存,所以匿名变量之间不存在重复声明,且匿名变量无法拿来使用,只能用来承接不想要的值。

总结

  1. 函数外的每个语句都必须以关键字开始(var、const、func等)
  2. := 不能在函数外使用
  3. _ 多用于占位,表示忽略值

常量

常量是程序运行期间不会改变的那些值。 变量声明是用 var,常量声明是用 const

常量在定义的时候必须赋值

const PI = 3.14156
const E  = 2.7182

批量声明

1
2
3
4
const (
    PI = 3.14156
    E  = 2.7182
)

批量声明时,如果省略了赋值则表示与上面一行的值相同。eg:

1
2
3
4
5
6
7
const (
    a = 100
    b
    c = 3.33
    d
    e
)

例子中,常量 ab 的值都是 100,cde 的值都是 3.33

iota

iota 是go语言中的 常量计数器,只能在常量的表达式中使用。

iota 在const 关键字出现时将被重置为 0

const 中每新增一行常量声明,将使 iota +1

iota 可理解为const 块中的行索引。

使用iota能简化定义,在枚举时很方便。

const (
    n1 = iota    // 0
    n2           // 1
    n3           // 2
    n4           // 3
)

func main() {
    fmt.Println(n1, n2, n3, n4)
}

// ----------------------------------------
// Output:
0 1 2 3

还有几个比较经典的例子:

  • 匿名变量插队

    1
    2
    3
    4
    5
    6
    const (
        n1 = iota // 0
        n2        // 1
        _
        n4        // 3
    )
    
  • 声明中间插队

    1
    2
    3
    4
    5
    6
    7
    8
    const (
        n1 = iota    // 0
        n2 = 100     // 100
        n3 = iota    // 2
        n4           // 3
        n5           // 4
    )
    const n6 = iota  // 0
    
  • 定义数量级

    1
    2
    3
    4
    5
    6
    7
    8
    const (
        _  = iota
        KB = 1 << (10 * iota)    // 10*1 == 10
        MB = 1 << (10 * iota)    // 10*2 == 20
        GB = 1 << (10 * iota)    // 10*3 == 30
        TB = 1 << (10 * iota)    // 10*4 == 40
        PB = 1 << (10 * iota)    // 10*5 == 50
    )
    
  • 多个 iota 定义在一行

    const (
        a, b = iota + 1, iota + 2 //1,2
        c, d                      //2,3
        e, f                      //3,4
    )
    
    func main() {
        fmt.Println(a, b, c, d, e, f)
    }
    
    // ----------------------------------------
    // Output:
    1 2 2 3 3 4
    
  • iota 只有在新起一行才会自增

  • iota 只有遇到新的 const 才会重置
  • iota 是从 0 开始的。

值类型和引用类型

 j = i

j = i

值类型int float bool string 指针,使用这些类型的变量直接指向存在内存中的值,存储在栈中。

 r1 = r2

r1 = r2

引用类型slices、maps、channel,被引用的变量会存储在堆中,以便垃圾回收。