指標是一個變數,其值為另一個變數的地址,即,記憶體地址。
指標型別的資料大小為固定值,32位系統為4位元組,64位系統為8位元組。
1、指標的定義和使用
取址符號:&
指標:*
傳過去一個地址,透過指標進行接收
定義一個指標:
var a int = 10
var p *int = &a
// 定义了一个指针,p的类型为*int,p指向a的地址
//通过指针修改值
*p = 20
fmt.Println(a) //20
不同於C/C++語言中的指標,go語言中的指標限制了指標的運算,不能透過修改指標運算的方式訪問其他記憶體的值
但是go語言在unsafe包中提供了一些方法,可以透過指標運算的方式訪問其他記憶體的值,但是這種方式是不安全的,不建議使用。
2、指標的初始化
指標未初始化時,預設值為nil
在定義指標時需要進行初始化
下面是幾種指標初始化寫法,按需要選擇,不是全部貼進同一個作用域:
var a int = 10
var p *int = &a
var p2 = new(int) //new函数返回一个指针,指向一个新的int类型的值,值为0
// 如果是结构体还能用下面的方式
p := &Person{}
取已有變數地址可以用 &,需要新零值物件時可以用 new;也可以用 &Person{} 這樣的寫法。
map、slice、channel的初始化最好使用make方式
需要解引用時,指標必須指向有效物件。nil map 可以讀取,但寫入前必須初始化。
3、swap與指標
func swap(a, b *int) {
t := *a
*a = *b
*b = t
}
func main() {
var a int = 10
var b int = 20
swap(&a, &b)
fmt.Println(a, b) //20 10
}
4、Go 中的 nil
nil 是指標、切片、map、channel、函式和介面等型別可以具有的零值。它不是所有型別的統一零值:整數是 0,布林值是 false,結構體的零值則是每個欄位各自的零值。
這裡有兩點容易記錯:nil slice 可以 append;nil map 可以讀,但不能直接寫。
package main
import "fmt"
func main() {
var nums []int
nums = append(nums, 1)
fmt.Println(nums) // [1]
var counts map[string]int
fmt.Println(counts["go"]) // 0
// counts["go"] = 1 // nil map 写入会 panic
counts = make(map[string]int)
counts["go"] = 1
fmt.Println(counts["go"]) // 1
}
空切片和 nil 切片的長度都可以是 0,但 slice == nil 的結果不同;切片也不能像兩個整數那樣直接互相用 == 比較。
另外,介面裡裝著一個有型別的 nil 指標時,介面本身可能不等於 nil。以後處理 error 返回值時也要注意這一點,不能只把 nil 理解成“任何東西都是空的”。
規則可以對照 Go 規範:append、索引表示式和零值。