go語言中指針有哪些運算
go語言沒有指標運算。 go語言的語法上是不支援指標運算的,所有指標都在可控的一個範圍內使用;但實際上,go語言可以透過unsafe套件的Pointer()方法把指標轉換為uintptr類型的數字,來間接實現指針運算。
本教學操作環境: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 強類型的特性,第三行程式碼也許是最具幹擾性的了,b 包含a變數的位址,但是我們想增加儲存在a 變數中的值。
這樣我們必須取消引用 b ,而是跟隨指標由 b 引用 a。
然後我們將該值加 1 後,儲存回 b 中儲存的記憶體位址上。
最後一行印了a 的值,可以看到a 的值已經增加為了201
##Go語言中的函數傳參都是值拷貝,當我們想要修改某個變數的時候,我們可以建立一個指向該變數位址的指標變數。
區別於C/C 中的指針,Go語言中的指針不能偏移和運算,是安全指針。
要搞清楚Go語言中的指標需要先知道3個概念:指標位址、指標型別和指標取值。
指標位址和指標型別
Go語言中的指標運算非常簡單,只需要記住兩個符號:&(取位址)和*(根據地址取值)。 每個變數在運行時都有一個位址,這個位址代表變數在記憶體中的位置。 Go語言中使用&字元放在變數前面對變數進行「取地址」操作。取變數指標的語法如下:
ptr := &v // v的类型为T
- v:代表被取位址的變量,類型為T
- ptr:用來接收位址的變量,ptr的型別就為*T,稱做T的指標型別。 *代表指針。
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語言中指針有哪些運算的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Go語言中使用RedisStream實現消息隊列時類型轉換問題在使用Go語言與Redis...

Go爬蟲Colly中的Queue線程問題探討在使用Go語言的Colly爬蟲庫時,開發者常常會遇到關於線程和請求隊列的問題。 �...

Go語言中用於浮點數運算的庫介紹在Go語言(也稱為Golang)中,進行浮點數的加減乘除運算時,如何確保精度是�...

GoLand中自定義結構體標籤不顯示怎麼辦?在使用GoLand進行Go語言開發時,很多開發者會遇到自定義結構體標籤在�...

Go語言中哪些庫是大公司開發或知名開源項目?在使用Go語言進行編程時,開發者常常會遇到一些常見的需求,�...

Go編程中的資源管理:Mysql和Redis的連接與釋放在學習Go編程過程中,如何正確管理資源,特別是與數據庫和緩存�...

VSCode中Golang泛型函數類型約束的自動刪除問題在使用VSCode編寫Golang代碼時,用戶可能會遇到一個奇怪的問題。當...

Go語言在構建高效且可擴展的系統中表現出色,其優勢包括:1.高性能:編譯成機器碼,運行速度快;2.並發編程:通過goroutines和channels簡化多任務處理;3.簡潔性:語法簡潔,降低學習和維護成本;4.跨平台:支持跨平台編譯,方便部署。
