首頁 >後端開發 >Golang >go語言中指針有哪些運算

go語言中指針有哪些運算

青灯夜游
青灯夜游原創
2023-01-04 10:30:293589瀏覽

go語言沒有指標運算。 go語言的語法上是不支援指標運算的,所有指標都在可控的一個範圍內使用;但實際上,go語言可以透過unsafe套件的Pointer()方法把指標轉換為uintptr類型的數字,來間接實現指針運算。

go語言中指針有哪些運算

本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。

到底什麼是指標呢?

記憶體就是一系列有序號的儲存單元,變數就是編譯器為記憶體位址分配的暱稱,那麼指標是什麼呢?

指標就是一個指向另一個記憶體位址變數的值

指標指向變數的記憶體位址,指標就像該變數值的記憶體位址一樣

我們來看一個程式碼片段

func main() {
    a := 200
    b := &a
    *b++
    fmt.Println(a)
}

在main 函數的第一行,我們定義了一個新的變數a ,並賦值為200。接下來我們定義了一個變數 b ,並將變數 a 的位址賦值給 b 。我們並不知道 a 的準確儲存位址,但是我們依然可以將 a 的位址儲存在變數 b 中。

go語言中指針有哪些運算

go語言中指針有哪些運算

因為Go 強類型的特性,第三行程式碼也許是最具幹擾性的了,b 包含a變數的位址,但是我們想增加儲存在a 變數中的值。

這樣我們必須取消引用 b ,而是跟隨指標由 b 引用 a。
然後我們將該值加 1 後,儲存回 b 中儲存的記憶體位址上。

最後一行印了a 的值,可以看到a 的值已經增加為了201

go語言中指針有哪些運算

go語言中指針有哪些運算

##Go語言中的函數傳參都是值拷貝,當我們想要修改某個變數的時候,我們可以建立一個指向該變數位址的指標變數

區別於C/C 中的指針,

Go語言中的指針不能偏移和運算,是安全指針

要搞清楚Go語言中的指標需要先知道3個概念:

指標位址、指標型別和指標取值

指標位址和指標型別

Go語言中的指標運算非常簡單,只需要記住兩個符號:&(取位址)和*(根據地址取值)。

每個變數在運行時都有一個位址,這個位址代表變數在記憶體中的位置。 Go語言中使用&字元放在變數前面對變數進行「取地址」操作。

取變數指標的語法如下:

ptr := &v    // v的类型为T

其中:

  • v:代表被取位址的變量,類型為T

  • ptr:用來接收位址的變量,ptr的型別就為*T,稱做T的指標型別。 *代表指針。

go語言中指針有哪些運算

func main() {
    a := 10
    b := &a
    fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
    fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
    fmt.Println(&b)                    // 0xc00000e018
}

指標運算子

1.指標運算子為左值時,我們可以更新目標物件的狀態;而為右值時則是為了取得目標的狀態。

func main() {
    x := 10
    var p *int = &x  //获取地址,保存到指针变量
    *p += 20        //用指针间接引用,并更新对象
    println(p, *p)  //输出指针所存储的地址,以及目标对象
}
輸出:

0xc000040780 30

2.指標型別支援相等運算符,但不能做加減運算和型別轉換。如果兩個指標指向同一位址,或都為nil,那麼它們相等。

func main() {
    x := 10
    p := &x

    p++   //编译报错 invalid operation: p++ (non-numeric type *int)
    var p2 *int = p+1  //invalid operation: p + 1 (mismatched types *int and int)
    p2 = &x
    println(p == p2)   //指向同一地址
}
可透過unsafe.Pointer將指標轉換為uintptr後進行加減法運算,但可能會造成非法存取。

指針運算

在很多golang 程式中,雖然用到了指針,但是不會對指針進行加減運算,這和C 程式是很不一樣的。 Golang 的官方入門學習工具(

go tour) 甚至說 Go 不支援指標算術。雖然實際上並不是這樣的,但我在一般的 go 程序中,好像確實沒見過指針運算(嗯,我知道你想寫不一般的程序)。

  • 但实际上,go 可以通过 unsafe.Pointer 来把指针转换为 uintptr 类型的数字,来间接实现指针运算。
  • 这里请注意,uintptr 是一种整数类型,而不是指针类型。

比如:

uintptr(unsafe.Pointer(&p)) + 1

就得到了 &p 的下一个字节的位置。然而,根据 《Go Programming Language》 的提示,我们最好直接把这个计算得到的内存地址转换为指针类型:

unsafe.Pointer(uintptr(unsafe.Pointer(&p) + 1))

因为 go 中是有垃圾回收机制的,如果某种 GC 挪动了目标值的内存地址,以整型来存储的指针数值,就成了无效的值。

同时也要注意,go 中对指针的 + 1,真的就只是指向了下一个字节,而 C 中 + 1 或者 ++ 考虑了数据类型的长度,会自动指向当前值结尾后的下一个字节(或者说,有可能就是下一个值的开始)。如果 go 中要想实现同样的效果,可以使用 unsafe.Sizeof 方法:

unsafe.Pointer(uintptr(unsafe.Pointer(&p) + unsafe.Sizeof(p)))

最后,另外一种常用的指针操作是转换指针类型。这也可以利用 unsafe 包来实现:

var a int64 = 1
(*int8)(unsafe.Pointer(&a))

如果你没有遇到过需要转换指针类型的需求,可以看看这个项目(端口扫描工具),其中构建 IP 协议首部的代码,就用到了指针类型转换。

【相关推荐:Go视频教程编程教学

以上是go語言中指針有哪些運算的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn