總結(jié)
- 指針對象是用來存儲內(nèi)存地址的數(shù)據(jù)類型
- &符號獲取對象的內(nèi)存地址
- *符號根據(jù)內(nèi)存地址獲取值, 只有指針對象可以使用該符號
指針
仔細看代碼注釋, 應該描述得足夠明細了
package main
import "fmt"
func main() {
// 重點句子1: 指針對象是用來存儲內(nèi)存地址的數(shù)據(jù)類型
// 重點句子2: &符號獲取對象的內(nèi)存地址
// 重點句子3: *符號根據(jù)內(nèi)存地址獲取值, 只有指針對象可以使用*符號
var p *int // 創(chuàng)建了一個int類型的指針對象
// fmt.Println(p) //此時 p 是 <nil>
// 創(chuàng)建一個int變量
var v = 20
fmt.Println(v) // 50 v得到了新值:50
fmt.Println(&v) // 0xc4200160a8 v的內(nèi)存地址沒有變化
// fmt.Println(*v) // 錯誤, v是一個int對象,不是一個指針對象
p = &v // &符號得到了v的內(nèi)存地址, 賦值給指針p
// 此時 p指針已經(jīng)有了一個內(nèi)存地址了
fmt.Println(p) // 0xc4200160a8 這個是v的內(nèi)存地址
fmt.Println(&p) // 0xc420016028 這個是p指針的內(nèi)存地址, 一般用不到
fmt.Println(*p) // *符號會根據(jù)p所保存的內(nèi)存地址,獲取到該內(nèi)存地址指向的值,即v的值
// 修改對象的值
v = 50
fmt.Println(v) // 50 v得到了新值:50
fmt.Println(&v) // 0xc4200160a8 v的內(nèi)存地址沒有變化
fmt.Println(p) // 0xc4200160a8 p還是這個v的地址,沒有修改
fmt.Println(*p) // 50 *符號得到內(nèi)存地址的值, v已經(jīng)修改了,
// 通過指針修改對象的值
*p = 100
fmt.Println(v) // 100 v得到了新值:100
fmt.Println(&v) // 0xc4200160a8 v的內(nèi)存地址沒有變化
fmt.Println(p) // 0xc4200160a8 p還是這個v的地址,沒有修改
fmt.Println(*p) // 100 *符號得到內(nèi)存地址的值, v已經(jīng)修改了,
}
結(jié)構(gòu)體和指針
package main
import "fmt"
// Vertex 聲明一個結(jié)構(gòu)體
type Vertex struct {
X int
Y int
}
func main() {
// 實例化一個結(jié)構(gòu)體
var v = Vertex{1, 2}
// 實例化一個結(jié)構(gòu)體指針
var p *Vertex
// 把結(jié)構(gòu)體的內(nèi)存地址復制給指針
p = &v
// 以上三行一般情況下省略為:
// 實例化一個結(jié)構(gòu)體指針
// var p = &Vertex{1, 2}
// 對比上一段普通指針的幾種情況
fmt.Println(v) // {1, 2} 這是結(jié)構(gòu)體值
fmt.Println(p) // &{1, 2} 這是結(jié)構(gòu)體指針和普通指針的區(qū)別 直接顯示對象地址 而不是0x123456的內(nèi)存地址
fmt.Println(*p) // {1, 2} 結(jié)構(gòu)體對象的值
fmt.Println(&p) // 和普通指針一樣, *p是指針對象的內(nèi)存地址, 和結(jié)構(gòu)體無關(guān)系
fmt.Println(p) // &{1, 2} 這是結(jié)構(gòu)體指針和普通指針的區(qū)別 直接顯示對象地址 而不是0x123456的內(nèi)存地址
// 根據(jù)上面這行的特性
fmt.Println(p.X) //1 可以直接訪問結(jié)構(gòu)體指針里的對象
fmt.Println(&v.X) //0xc420096010 v.X的內(nèi)存地址
fmt.Println(&p.X) //0xc4200160b0 &p.X的內(nèi)存地址和 v.X是一樣的,因為它們是同一個對象
}