Golang——指针的使用、数组指针和指针数组、指针与切片、指针与结构体、多级指针
指針:
- 指針是一個(gè)特殊的變量,因?yàn)榇鎯?chǔ)的數(shù)據(jù)不僅僅是一個(gè)普通的數(shù)據(jù),而是一個(gè)變量的內(nèi)存地址,指針本身也是有內(nèi)存地址的
- 指針的數(shù)據(jù)類型有int、float、bool、string、數(shù)組、結(jié)構(gòu)體
- 指針的作用就是可以通過(guò)變量/對(duì)象的內(nèi)存地址去操作變量/對(duì)象
- 并非所有對(duì)象都能進(jìn)行取地址操作,但變量總是能正確返回(addressable)。指針運(yùn)算符為左值時(shí),我們可更新目標(biāo)對(duì)象狀態(tài),而為右值時(shí)則是為了獲取目標(biāo)狀態(tài)。
注意:
- 空指針:未初始化的指針 使用*p獲取
- 野指針:被無(wú)效地址空間初始化
- 取址運(yùn)算符&用于獲取對(duì)象地址
- 指針運(yùn)算符*用于間接引用目標(biāo)對(duì)象
- 二級(jí)指針(一個(gè)指針指向另一個(gè)指針)**T,或包含包名*package.T
指針定義:
定義格式:
var 指針名 *類型獲取內(nèi)存地址格式:
&變量/指針通過(guò)指針修改變量的值:
// *指針變量是獲取到內(nèi)存地址指向的變量值,拿到后可以再修改,或者其它操作 *指針變量 = 值演示:
func pointerDemo01() {a := 10// 定義一個(gè)指針變量p,并把a(bǔ)的內(nèi)存地址賦值給pvar p *int// &可以獲取內(nèi)存地址p = &a// 對(duì)比a的內(nèi)存地址和p變量存的數(shù)據(jù)是一樣的fmt.Println("變量a的內(nèi)存地址:", &a)fmt.Println("指針p的數(shù)據(jù):", p)fmt.Println("指針p存的數(shù)據(jù):", *p)fmt.Println("指針p的內(nèi)存地址:", &p)// 通過(guò)指針修改數(shù)據(jù),a的數(shù)據(jù)也同步修改*p = 222fmt.Println(a) }指針類型支持相等運(yùn)算符,但不能做加減法運(yùn)算和直接類型轉(zhuǎn)換。如果兩個(gè)指針指向同一地址,或都為nil,那么它們相等
func main() {x := 10p := &xp++ // 無(wú)效運(yùn)算:p++ (non-numeric type *int)var p2 *int = p + 1 // 無(wú)效運(yùn)算: p + 1 (mismatched types *int and int)p2 = &xprintln(p == p2) }零長(zhǎng)度(zero-size)對(duì)象的地址是否相等和具體的實(shí)現(xiàn)版本有關(guān),不過(guò)肯定不等于nil
即便長(zhǎng)度為0,可該對(duì)象依然是合法存在的,也擁有內(nèi)存地址,這與nil語(yǔ)義完全不同。
在runtime/malloc.go里有個(gè)zerobase全局變量,所有通過(guò)mallocgc分配的零長(zhǎng)度對(duì)象都使用該地址。不過(guò)下例中,對(duì)象a、b在棧上分配,并未調(diào)用mallocgc函數(shù)
打印結(jié)果:
0x14000096f68 0x14000096f68 false false操作指針的3個(gè)注意事項(xiàng):
指針作為函數(shù)參數(shù):
在函數(shù)中修改變量值,是不影響原來(lái)的變量的,可以通過(guò)指針去修改
不通過(guò)指針的時(shí)候,修改原來(lái)的變量,雖然變量都是a,但是內(nèi)存地址是不一樣的,所以在函數(shù)中修改完以后會(huì)發(fā)現(xiàn)原來(lái)的變量并沒(méi)有被修改,但是通過(guò)指針去修改的時(shí)候是因?yàn)橹赶虻氖莾?nèi)存地址,所以對(duì)函數(shù)中的a進(jìn)行操作,其實(shí)就是對(duì)原來(lái)的a進(jìn)行操作,所以可以將原來(lái)的變量值修改掉
演示:
func main() {a := 10pointerDemo03(&a)fmt.Println(a) }// 注意,指針作為函數(shù)的時(shí)候,參數(shù)也要加上* func pointerDemo03(a *int) {*a = 20 }數(shù)組指針:
要分清指針數(shù)組和數(shù)組指針的區(qū)別。指針數(shù)組是指元素為指針類型的數(shù)組,數(shù)組指針是獲取數(shù)組變量的地址
var 數(shù)組指針變量 *[索引] 類型演示:
func pointerDemo05() {arr := [10]int{1, 2, 3, 3, 4, 5}var p *[10]intp = &arrfmt.Println(*p) // 獲取數(shù)組中的全部數(shù)據(jù)fmt.Println((*p)[0]) // 獲取指定數(shù)組中索引的數(shù)據(jù),因?yàn)?p是先運(yùn)算,所以要先加括號(hào),否則編譯保存fmt.Println(p[0]) // 獲取指定數(shù)組中索引的數(shù)據(jù),這個(gè)格式和加括號(hào)一樣,但是簡(jiǎn)化的寫(xiě)法for i := 0; i < len(p); i++ {fmt.Print(p[i], ",")} }數(shù)組作為函數(shù)參數(shù):
func main() {arr := [10]int{1, 2, 3, 3, 4, 5}var p *[10]intp = &arrpointerDemo06(p) }func pointerDemo06(p *[10]int) {p[0] = 111fmt.Println(p) }指針數(shù)組:
指針數(shù)組指的是元素為指針類型的數(shù)組(一個(gè)數(shù)組中存儲(chǔ)的都是指針),它就是一個(gè)存儲(chǔ)了地址的數(shù)組。
定義格式:
var 數(shù)組名 [索引] *類型演示:
func pointerDemo07() {var p [2]*inta := 10b := 20// 變量a的內(nèi)存地址保存在指針數(shù)組p的0索引,b保存在1索引p[0] = &ap[1] = &bfmt.Println(p) // 獲取p數(shù)組中的內(nèi)存地址fmt.Println(*p[0], *p[1]) // 獲取p數(shù)組中的指定索引數(shù)據(jù)for i := 0; i < len(p); i++ {fmt.Println(*p[i]) // 獲取p數(shù)組中的所有的數(shù)據(jù)}for key, value := range p {fmt.Println(key, *value)} }指針與切片:
其實(shí)就是定義指針,指向切片
演示:
func pointerDemo08() {s := []int{1, 2, 3, 4, 5}var p *[]intp = &sfmt.Println(*p)fmt.Println((*p)[0]) // 指針切片中沒(méi)有簡(jiǎn)化的寫(xiě)法,只能加括號(hào)先運(yùn)算指針,再運(yùn)算切片for i := 0; i < len(*p); i++ {fmt.Print("fori方式:", (*p)[i], ",")}for key, value := range *p {fmt.Println("range方式:", key, value)} }指針與結(jié)構(gòu)體:
其實(shí)就是定義指針,指向結(jié)構(gòu)體
演示:
type Student struct {// 成員名稱不加var關(guān)鍵字id intname stringage intaddr string }func pointerDemo09() {stu := Student{001, "itzhuzhu", 23, "廣州"}var p *Studentp = &stufmt.Println(*p) // 獲取全部fmt.Println((*p).name) // 獲取指定的數(shù)據(jù)fmt.Println(p.name) // 結(jié)構(gòu)體指針中也是有簡(jiǎn)化寫(xiě)法的p.addr = "深圳"fmt.Println(*p) }將結(jié)構(gòu)體指針作為函數(shù)參數(shù):
func main() {stu := Student{001, "itzhuzhu", 23, "廣州"}var p *Studentp = &stupointerDemo10(p)fmt.Println(stu) }```go func pointerDemo10(p *Student) {p.addr = "深圳" }多級(jí)指針:
多級(jí)指針指的是,存放的都是上一級(jí)指針的內(nèi)存地址,二級(jí)指針存的是一級(jí)指針的內(nèi)存地址,以此類推,多級(jí)指針的概念和二維數(shù)組的概念類似。多級(jí)指針可以無(wú)限定義級(jí)別,幾級(jí)指針定義的時(shí)候就要寫(xiě)幾個(gè)*
定義格式:
var 指針變量名 *類型 // 幾級(jí)指針就寫(xiě)幾個(gè)* 一個(gè)* 就是一級(jí)指針演示:
func pointerDemo11() {a := 10var p *intp = &a// 定義二級(jí)指針,var p2 **int//var p3 ***int//var p4 ****intp2 = &pfmt.Println(**p2) // 10 }總結(jié)
以上是生活随笔為你收集整理的Golang——指针的使用、数组指针和指针数组、指针与切片、指针与结构体、多级指针的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python 灰度改二值,Python
- 下一篇: XPath表达式