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