欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解讀unsafe.Pointer和uintptr的區(qū)別

 更新時(shí)間:2023年02月10日 09:07:14   作者:Generalzy  
這篇文章主要介紹了解讀unsafe.Pointer和uintptr的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

unsafe 包

func Alignof(x ArbitraryType) uintptr
func Offsetof(x ArbitraryType) uintptr
func Sizeof(x ArbitraryType) uintptr
type ArbitraryType int
type Pointer *ArbitraryType

在unsafe包中,只提供了3個(gè)函數(shù),兩個(gè)類型。就這么少的量,卻有著超級(jí)強(qiáng)悍的功能。

ArbitraryType

// ArbitraryType is here for the purposes of documentation only and is not actually
// part of the unsafe package. It represents the type of an arbitrary Goexpression.

// ArbitryType僅用于文檔目的,實(shí)際上并非不安全包的一部分。它表示任意Go表達(dá)式的類型。
type ArbitraryType int

ArbitraryType 是以int為基礎(chǔ)定義的一個(gè)新類型,但是Go 語(yǔ)言u(píng)nsafe包中,對(duì)ArbitraryType賦予了特殊的意義,通常,把interface{}看作是任意類型,那么ArbitraryType這個(gè)類型,在Go 語(yǔ)言系統(tǒng)中,比interface{}還要隨意。

Pointer

Pointer 是ArbitraryType指針類型為基礎(chǔ)的新類型,在Go 語(yǔ)言系統(tǒng)中,可以把Pointer類型,理解成任何指針的親爹。

Go 語(yǔ)言的指針類型長(zhǎng)度與int類型長(zhǎng)度,在內(nèi)存中占用的字節(jié)數(shù)是一樣的。ArbitraryType類型的變量也可以是指針。

// Alignof返回變量對(duì)齊字節(jié)數(shù)量
func Alignof(x ArbitraryType) uintptr
// Offsetof返回變量指定屬性的偏移量,所以如果變量是一個(gè)struct類型,不能直接將這個(gè)struct類型的變量當(dāng)作參數(shù),只能將這個(gè)struct類型變量的屬性當(dāng)作參數(shù)。
func Offsetof(x ArbitraryType) uintptr
// Sizeof 返回變量在內(nèi)存中占用的字節(jié)數(shù),切記,如果是slice,則不會(huì)返回這個(gè)slice在內(nèi)存中的實(shí)際占用長(zhǎng)度。
func Sizeof(x ArbitraryType) uintptr

unsafe中,通過ArbitraryType 、Pointer 這兩個(gè)類型,可以將其他類型都轉(zhuǎn)換過來,然后通過這三個(gè)函數(shù),分別能取長(zhǎng)度,偏移量,對(duì)齊字節(jié)數(shù),就可以在虛擬內(nèi)存中來回調(diào)度。

指針運(yùn)算

  • uintptr這個(gè)基礎(chǔ)類型,在Go 語(yǔ)言中,字節(jié)長(zhǎng)度是與int一致。
  • 通常Pointer不能參與指針運(yùn)算,比如要在某個(gè)指針地址上加上一個(gè)偏移量,Pointer是不能做這個(gè)運(yùn)算的
  • 只有將Pointer類型先轉(zhuǎn)換成uintptr類型,做完地址加減法運(yùn)算后,再轉(zhuǎn)換成Pointer類型,通過*操作達(dá)到取值、修改值的目的。
  • unsafe.Pointer其實(shí)就是類似C的void *,在Go 語(yǔ)言中是用于各種指針相互轉(zhuǎn)換的橋梁,也即是通用指針。它可以讓任意類型的指針實(shí)現(xiàn)相互轉(zhuǎn)換,也可以將任意類型的指針轉(zhuǎn)換為 uintptr 進(jìn)行指針運(yùn)算。
  • uintptr是Go 語(yǔ)言的內(nèi)置類型,是能存儲(chǔ)指針的整型, uintptr 的底層類型是int,它和unsafe.Pointer可相互轉(zhuǎn)換。

unsafe.Pointer和uintptr的區(qū)別

  • unsafe.Pointer只是單純的通用指針類型,用于轉(zhuǎn)換不同類型指針,它不可以參與指針運(yùn)算;
  • 而uintptr是用于指針運(yùn)算的,GC 不把 uintptr 當(dāng)指針,也就是說 uintptr 無(wú)法持有對(duì)象, uintptr 類型的目標(biāo)會(huì)被回收;
  • unsafe.Pointer 可以和 普通指針 進(jìn)行相互轉(zhuǎn)換;
  • unsafe.Pointer 可以和 uintptr 進(jìn)行相互轉(zhuǎn)換。

unsafe包簡(jiǎn)單使用

準(zhǔn)備結(jié)構(gòu)體,成員不導(dǎo)出

初始化結(jié)構(gòu)體

func main() {
	s:=pkg.UnsafeStruct{}
	// {0 0}
	fmt.Println(s)
}

眾所周知,結(jié)構(gòu)體的地址就是第一個(gè)成員的地址

func main() {
	s:=pkg.UnsafeStruct{}

	// 取成員1
	field1Pointer:=unsafe.Pointer(&s)
	fmt.Println(field1Pointer)
	// 轉(zhuǎn)為int32類型指針
	field1Ptr:=(*int32)(field1Pointer)
	fmt.Println(*field1Ptr)
}

賦值,可以看到私有字段已經(jīng)被改變

func main() {
	s:=pkg.UnsafeStruct{}

	// 取成員1
	field1Pointer:=unsafe.Pointer(&s)
	fmt.Println(field1Pointer)
	// 轉(zhuǎn)為int32類型指針
	field1Ptr:=(*int32)(field1Pointer)
	fmt.Println(*field1Ptr)

	// 賦值
	*field1Ptr = 10
	fmt.Println(s)
}

利用偏移量改變字段2的值

func main() {
	s:=pkg.UnsafeStruct{}

	// 取成員1
	field1Pointer:=unsafe.Pointer(&s)
	fmt.Println(field1Pointer)
	// 轉(zhuǎn)為int32類型指針
	field1Ptr:=(*int32)(field1Pointer)
	fmt.Println(*field1Ptr)

	// 賦值
	*field1Ptr = 1314
	fmt.Println(s)

	// 獲取成員2的Pointer
	filed2Pointer:= unsafe.Pointer(uintptr(field1Pointer)+ unsafe.Sizeof(int64(0)))
	fmt.Println(filed2Pointer)
	// 轉(zhuǎn)為int64類型指針
	field2Ptr:=(*int64)(filed2Pointer)
	fmt.Println(*field2Ptr)

	// 賦值
	*field2Ptr = 520
	fmt.Println(s)
}

成員聲明為int32和int64是為了避免對(duì)齊的影響,否則就要加上對(duì)齊值

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Golang并發(fā)編程重點(diǎn)講解

    Golang并發(fā)編程重點(diǎn)講解

    這篇文章主要介紹了Golang并發(fā)編程,在許多環(huán)境中,實(shí)現(xiàn)對(duì)共享變量的正確訪問所需要的微妙之處使并發(fā)編程變得困難。Go鼓勵(lì)一種不同的方法,在這種方法中,共享值在通道中傳遞,實(shí)際上,從不由單獨(dú)的執(zhí)行線程主動(dòng)共享
    2023-04-04
  • 揭秘Go語(yǔ)言中的反射機(jī)制

    揭秘Go語(yǔ)言中的反射機(jī)制

    在Go語(yǔ)言中,反射是通過reflect包來實(shí)現(xiàn)的,通過使用反射,我們可以在運(yùn)行時(shí)獲取對(duì)象的類型信息、訪問對(duì)象的字段和方法、動(dòng)態(tài)調(diào)用方法等,反射在很多場(chǎng)景下都非常有用,比如編寫通用的代碼、實(shí)現(xiàn)對(duì)象的序列化和反序列化、實(shí)現(xiàn)依賴注入等,需要的朋友可以參考下
    2023-10-10
  • go語(yǔ)言生成隨機(jī)數(shù)和隨機(jī)字符串的實(shí)現(xiàn)方法

    go語(yǔ)言生成隨機(jī)數(shù)和隨機(jī)字符串的實(shí)現(xiàn)方法

    隨機(jī)數(shù)在很多時(shí)候都可以用到,尤其是登錄時(shí),本文就詳細(xì)的介紹一下go語(yǔ)言生成隨機(jī)數(shù)和隨機(jī)字符串的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-12-12
  • Go?Web實(shí)戰(zhàn)之創(chuàng)建項(xiàng)目及增加日志功能

    Go?Web實(shí)戰(zhàn)之創(chuàng)建項(xiàng)目及增加日志功能

    這篇文章主要為大家詳細(xì)介紹了Go?Web項(xiàng)目中如何實(shí)現(xiàn)創(chuàng)建項(xiàng)目及增加日志功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-11-11
  • Go語(yǔ)言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器

    Go語(yǔ)言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器

    本文主要介紹了Go語(yǔ)言實(shí)現(xiàn)廣播式并發(fā)聊天服務(wù)器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • Go語(yǔ)言變量與基礎(chǔ)數(shù)據(jù)類型詳情

    Go語(yǔ)言變量與基礎(chǔ)數(shù)據(jù)類型詳情

    Go 是靜態(tài)(編譯型)語(yǔ)言,是區(qū)別于解釋型語(yǔ)言的弱類型語(yǔ)言(靜態(tài):類型固定,強(qiáng)類型:不同類型不允許直接運(yùn)算),下面文章將對(duì)其進(jìn)行詳細(xì)介紹,需要的朋友可以參考一下
    2021-09-09
  • Golang無(wú)限緩存channel的設(shè)計(jì)與實(shí)現(xiàn)解析

    Golang無(wú)限緩存channel的設(shè)計(jì)與實(shí)現(xiàn)解析

    這篇文章主要為大家介紹了Golang無(wú)限緩存channel的設(shè)計(jì)與實(shí)現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Golang中g(shù)oroutine和channel使用介紹深入分析

    Golang中g(shù)oroutine和channel使用介紹深入分析

    一次只做一件事情并不是完成任務(wù)最快的方法,一些大的任務(wù)可以拆解成若干個(gè)小任務(wù),goroutine可以讓程序同時(shí)處理幾個(gè)不同的任務(wù),goroutine使用channel來協(xié)調(diào)它們的工作,channel允許goroutine互相發(fā)送數(shù)據(jù)并同步,這樣一個(gè)goroutine就不會(huì)領(lǐng)先于另一個(gè)goroutine
    2023-01-01
  • 如何判斷Golang接口是否實(shí)現(xiàn)的操作

    如何判斷Golang接口是否實(shí)現(xiàn)的操作

    這篇文章主要介紹了如何判斷Golang接口是否實(shí)現(xiàn)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • golang HTTP 服務(wù)器 處理 日志/Stream流的操作

    golang HTTP 服務(wù)器 處理 日志/Stream流的操作

    這篇文章主要介紹了golang HTTP 服務(wù)器 處理 日志/Stream流的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評(píng)論