亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁(yè) > 知識(shí)庫(kù) > golang利用unsafe操作未導(dǎo)出變量-Pointer使用詳解

golang利用unsafe操作未導(dǎo)出變量-Pointer使用詳解

熱門(mén)標(biāo)簽:濱州自動(dòng)電銷(xiāo)機(jī)器人排名 阿里云ai電話(huà)機(jī)器人 浙江高頻外呼系統(tǒng)多少錢(qián)一個(gè)月 釘釘有地圖標(biāo)注功能嗎 建造者2地圖標(biāo)注 惠州電銷(xiāo)防封電話(huà)卡 汕頭小型外呼系統(tǒng) 鄭州亮點(diǎn)科技用的什么外呼系統(tǒng) 黃岡人工智能電銷(xiāo)機(jī)器人哪個(gè)好

前言

unsafe.Pointer其實(shí)就是類(lèi)似C的void *,在golang中是用于各種指針相互轉(zhuǎn)換的橋梁。uintptr是golang的內(nèi)置類(lèi)型,是能存儲(chǔ)指針的整型,uintptr的底層類(lèi)型是int,它和unsafe.Pointer可相互轉(zhuǎn)換。uintptr和unsafe.Pointer的區(qū)別就是:unsafe.Pointer只是單純的通用指針類(lèi)型,用于轉(zhuǎn)換不同類(lèi)型指針,它不可以參與指針運(yùn)算;而uintptr是用于指針運(yùn)算的,GC 不把 uintptr 當(dāng)指針,也就是說(shuō) uintptr 無(wú)法持有對(duì)象,uintptr類(lèi)型的目標(biāo)會(huì)被回收。golang的unsafe包很強(qiáng)大,基本上很少會(huì)去用它。它可以像C一樣去操作內(nèi)存,但由于golang不支持直接進(jìn)行指針運(yùn)算,所以用起來(lái)稍顯麻煩。

切入正題。利用unsafe包,可操作私有變量(在golang中稱(chēng)為“未導(dǎo)出變量”,變量名以小寫(xiě)字母開(kāi)始),下面是具體例子。

在$GOPATH/src下建立poit包,并在poit下建立子包p,目錄結(jié)構(gòu)如下:

$GOPATH/src

----poit

--------p

------------v.go

--------main.go

以下是v.go的代碼:

package p

import (
 "fmt"
)

type V struct {
 i int32
 j int64
}

func (this V) PutI() {
 fmt.Printf("i=%d\n", this.i)
}

func (this V) PutJ() {
 fmt.Printf("j=%d\n", this.j)
}

意圖很明顯,我是想通過(guò)unsafe包來(lái)實(shí)現(xiàn)對(duì)V的成員i和j賦值,然后通過(guò)PutI()和PutJ()來(lái)打印觀察輸出結(jié)果。

以下是main.go源代碼:

package main

import (
 "poit/p"
 "unsafe"
)

func main() {
 var v *p.V = new(p.V)
 var i *int32 = (*int32)(unsafe.Pointer(v))
 *i = int32(98)
 var j *int64 = (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + uintptr(unsafe.Sizeof(int32(0)))))
 *j = int64(763)
 v.PutI()
 v.PutJ()
}

當(dāng)然會(huì)有些限制,比如需要知道結(jié)構(gòu)體V的成員布局,要修改的成員大小以及成員的偏移量。我們的核心思想就是:結(jié)構(gòu)體的成員在內(nèi)存中的分配是一段連續(xù)的內(nèi)存,結(jié)構(gòu)體中第一個(gè)成員的地址就是這個(gè)結(jié)構(gòu)體的地址,您也可以認(rèn)為是相對(duì)于這個(gè)結(jié)構(gòu)體偏移了0。相同的,這個(gè)結(jié)構(gòu)體中的任一成員都可以相對(duì)于這個(gè)結(jié)構(gòu)體的偏移來(lái)計(jì)算出它在內(nèi)存中的絕對(duì)地址。

具體來(lái)講解下main方法的實(shí)現(xiàn):

var v *p.V = new(p.V)

new是golang的內(nèi)置方法,用來(lái)分配一段內(nèi)存(會(huì)按類(lèi)型的零值來(lái)清零),并返回一個(gè)指針。所以v就是類(lèi)型為p.V的一個(gè)指針。

var i *int32 = (*int32)(unsafe.Pointer(v))

將指針v轉(zhuǎn)成通用指針,再轉(zhuǎn)成int32指針。這里就看到了unsafe.Pointer的作用了,您不能直接將v轉(zhuǎn)成int32類(lèi)型的指針,那樣將會(huì)panic。剛才說(shuō)了v的地址其實(shí)就是它的第一個(gè)成員的地址,所以這個(gè)i就很顯然指向了v的成員i,通過(guò)給i賦值就相當(dāng)于給v.i賦值了,但是別忘了i只是個(gè)指針,要賦值得解引用。

*i = int32(98)

現(xiàn)在已經(jīng)成功的改變了v的私有成員i的值,好開(kāi)心_

但是對(duì)于v.j來(lái)說(shuō),怎么來(lái)得到它在內(nèi)存中的地址呢?其實(shí)我們可以獲取它相對(duì)于v的偏移量(unsafe.Sizeof可以為我們做這個(gè)事),但我上面的代碼并沒(méi)有這樣去實(shí)現(xiàn)。各位別急,一步步來(lái)。

var j *int64 = (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + uintptr(unsafe.Sizeof(int32(0)))))

其實(shí)我們已經(jīng)知道v是有兩個(gè)成員的,包括i和j,并且在定義中,i位于j的前面,而i是int32類(lèi)型,也就是說(shuō)i占4個(gè)字節(jié)。所以j是相對(duì)于v偏移了4個(gè)字節(jié)。您可以用uintptr(4)或uintptr(unsafe.Sizeof(int32(0)))來(lái)做這個(gè)事。unsafe.Sizeof方法用來(lái)得到一個(gè)值應(yīng)該占用多少個(gè)字節(jié)空間。注意這里跟C的用法不一樣,C是直接傳入類(lèi)型,而golang是傳入值。之所以轉(zhuǎn)成uintptr類(lèi)型是因?yàn)樾枰鲋羔樳\(yùn)算。v的地址加上j相對(duì)于v的偏移地址,也就得到了v.j在內(nèi)存中的絕對(duì)地址,別忘了j的類(lèi)型是int64,所以現(xiàn)在的j就是一個(gè)指向v.j的指針,接下來(lái)給它賦值:

*j = int64(763)

好吧,現(xiàn)在貌視一切就緒了,來(lái)打印下:

v.PutI()
v.PutJ()

如果您看到了正確的輸出,那恭喜您,您做到了!

但是,別忘了上面的代碼其實(shí)是有一些問(wèn)題的,您發(fā)現(xiàn)了嗎?

在p目錄下新建w.go文件,代碼如下:

package p

import (
 "fmt"
 "unsafe"
)

type W struct {
 b byte
 i int32
 j int64
}

func init() {
 var w *W = new(W)
 fmt.Printf("size=%d\n", unsafe.Sizeof(*w))
}

需要修改main.go的代碼嗎?不需要,我們只是來(lái)測(cè)試一下。w.go里定義了一個(gè)特殊方法init,它會(huì)在導(dǎo)入p包時(shí)自動(dòng)執(zhí)行,別忘了我們有在main.go里導(dǎo)入p包。每個(gè)包都可定義多個(gè)init方法,它們會(huì)在包被導(dǎo)入時(shí)自動(dòng)執(zhí)行(在執(zhí)行main方法前被執(zhí)行,通常用于初始化工作),但是,最好在一個(gè)包中只定義一個(gè)init方法,否則您或許會(huì)很難預(yù)期它的行為)。我們來(lái)看下它的輸出:

size=16

等等,好像跟我們想像的不一致。來(lái)手動(dòng)計(jì)算一下:b是byte類(lèi)型,占1個(gè)字節(jié);i是int32類(lèi)型,占4個(gè)字節(jié);j是int64類(lèi)型,占8個(gè)字節(jié),1+4+8=13。這是怎么回事呢?這是因?yàn)榘l(fā)生了對(duì)齊。在struct中,它的對(duì)齊值是它的成員中的最大對(duì)齊值。每個(gè)成員類(lèi)型都有它的對(duì)齊值,可以用unsafe.Alignof方法來(lái)計(jì)算,比如unsafe.Alignof(w.b)就可以得到b在w中的對(duì)齊值。同理,我們可以計(jì)算出w.b的對(duì)齊值是1,w.i的對(duì)齊值是4,w.j的對(duì)齊值也是4。如果您認(rèn)為w.j的對(duì)齊值是8那就錯(cuò)了,所以我們前面的代碼能正確執(zhí)行(試想一下,如果w.j的對(duì)齊值是8,那前面的賦值代碼就有問(wèn)題了。也就是說(shuō)前面的賦值中,如果v.j的對(duì)齊值是8,那么v.i跟v.j之間應(yīng)該有4個(gè)字節(jié)的填充。所以得到正確的對(duì)齊值是很重要的)。對(duì)齊值最小是1,這是因?yàn)榇鎯?chǔ)單元是以字節(jié)為單位。所以b就在w的首地址,而i的對(duì)齊值是4,它的存儲(chǔ)地址必須是4的倍數(shù),因此,在b和i的中間有3個(gè)填充,同理j也需要對(duì)齊,但因?yàn)閕和j之間不需要填充,所以w的Sizeof值應(yīng)該是13+3=16。如果要通過(guò)unsafe來(lái)對(duì)w的三個(gè)私有成員賦值,b的賦值同前,而i的賦值則需要跳過(guò)3個(gè)字節(jié),也就是計(jì)算偏移量的時(shí)候多跳過(guò)3個(gè)字節(jié),同理j的偏移可以通過(guò)簡(jiǎn)單的數(shù)學(xué)運(yùn)算就能得到。

比如也可以通過(guò)unsafe來(lái)靈活取值:

package main

import (
 "fmt"
 "unsafe"
)

func main() {
 var b []byte = []byte{'a', 'b', 'c'}
 var c *byte = b[0]
 fmt.Println(*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + uintptr(1))))
}

關(guān)于填充,F(xiàn)astCGI協(xié)議就用到了。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

您可能感興趣的文章:
  • Golang常用環(huán)境變量說(shuō)明與設(shè)置詳解
  • Golang中的變量學(xué)習(xí)小結(jié)
  • golang中值類(lèi)型/指針類(lèi)型的變量區(qū)別總結(jié)
  • Golang常見(jiàn)錯(cuò)誤之值拷貝和for循環(huán)中的單一變量詳解
  • 詳解Golang編程中的常量與變量
  • Golang學(xué)習(xí)筆記(二):類(lèi)型、變量、常量
  • Golang 變量申明的三種方式

標(biāo)簽:東營(yíng) 滄州 昭通 晉中 駐馬店 瀘州 泰安 阿壩

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《golang利用unsafe操作未導(dǎo)出變量-Pointer使用詳解》,本文關(guān)鍵詞  golang,利用,unsafe,操作,未,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《golang利用unsafe操作未導(dǎo)出變量-Pointer使用詳解》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于golang利用unsafe操作未導(dǎo)出變量-Pointer使用詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    韩国毛片免费大片| 日韩中文字幕在线播放| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 免费的黄色小视频| 精品在线免费播放| 日韩一级黄色| 午夜家庭影院| 久久国产精品自由自在| 欧美激情伊人| 日韩在线观看视频免费| 国产一区免费观看| 高清一级毛片一本到免费观看| 毛片的网站| 欧美国产日韩一区二区三区| 99色视频在线| 可以免费看污视频的网站| 成人免费福利片在线观看| 精品久久久久久中文字幕一区| 天天做日日爱| 午夜久久网| 麻豆系列 在线视频| 国产亚洲精品aaa大片| 亚洲精品影院久久久久久| 欧美一级视| 国产高清视频免费观看| 国产亚洲精品成人a在线| 九九九国产| 精品国产三级a∨在线观看| 久久国产精品只做精品| 欧美另类videosbestsex高清| 日韩专区一区| 欧美18性精品| 国产网站在线| 你懂的日韩| 999久久66久6只有精品| 一级毛片视频在线观看| 国产91丝袜在线播放0| 欧美a免费| 91麻豆精品国产高清在线| 久久精品店| 精品国产一级毛片| 九九九网站| 欧美a免费| 精品视频免费在线| 成人影视在线观看| 一级毛片视频在线观看| 成人影视在线观看| 精品久久久久久中文字幕2017| 国产成人啪精品| 一本伊大人香蕉高清在线观看| 九九免费精品视频| 免费国产一级特黄aa大片在线| 日韩中文字幕一区| 一 级 黄 中国色 片| 欧美国产日韩久久久| 高清一级做a爱过程不卡视频| 毛片高清| 国产一区免费在线观看| 免费毛片播放| 国产福利免费观看| 韩国毛片免费大片| 国产精品自拍在线| 国产成人欧美一区二区三区的| 91麻豆精品国产片在线观看| 日韩一级黄色| 日韩免费在线| 久久99中文字幕久久| 久久精品免视看国产明星| 国产视频一区二区在线观看| 久草免费在线观看| 欧美日本免费| 91麻豆精品国产高清在线| 91麻豆精品国产综合久久久| 成人高清视频免费观看| 你懂的日韩| 沈樵在线观看福利| 日韩一级黄色| 高清一级毛片一本到免费观看| 久久久久久久男人的天堂| 国产成人精品综合在线| 精品国产一区二区三区精东影业| 日韩免费片| 尤物视频网站在线观看| 欧美一区二区三区在线观看| 日韩免费在线| 成人免费网站视频ww| 九九精品影院| 亚洲 激情| 国产成人啪精品| 麻豆污视频| 久久国产精品只做精品| 天天做日日爱| 成人影视在线观看| 精品视频免费观看| 99久久精品国产麻豆| 天天色色网| 国产韩国精品一区二区三区| 日本伦理网站| 韩国三级视频网站| 亚洲 激情| 99热视热频这里只有精品| 亚洲精品中文一区不卡| 精品国产三级a∨在线观看| 91麻豆国产| 欧美日本免费| 国产成人啪精品视频免费软件| 四虎影视库| 91麻豆爱豆果冻天美星空| 91麻豆精品国产高清在线| 日日夜夜婷婷| 欧美a级v片不卡在线观看| 四虎影视库| 亚洲精品中文字幕久久久久久| 午夜家庭影院| 日本免费看视频| 精品视频在线观看一区二区三区| 欧美1区2区3区| 日本特黄一级| 毛片的网站| 国产国语对白一级毛片| 国产成人精品一区二区视频| 国产一区二区精品| 你懂的国产精品| 亚欧乱色一区二区三区| 二级片在线观看| 日韩免费在线| 国产一区二区精品久久91| 国产91精品一区| 黄色免费三级| 亚洲精品影院| 久久精品人人做人人爽97| 成人影院一区二区三区| 国产成a人片在线观看视频| 欧美a免费| 日日爽天天| 国产一级强片在线观看| 国产国语在线播放视频| 亚飞与亚基在线观看| 国产高清在线精品一区a| 999久久66久6只有精品| 久久福利影视| 九九精品影院| 欧美激情一区二区三区在线播放| 国产成人精品综合久久久| 黄色免费三级| 91麻豆tv| 免费毛片基地| 国产不卡精品一区二区三区| 日韩在线观看视频黄| 你懂的国产精品| 日本免费区| 99色视频| 国产成+人+综合+亚洲不卡 | 亚洲天堂在线播放| 国产精品免费久久| 国产麻豆精品hdvideoss| 国产一区免费观看| 亚欧成人乱码一区二区 | a级黄色毛片免费播放视频| 国产一区免费在线观看| 四虎影视久久久| 国产不卡在线观看| 免费国产在线观看| 欧美一级视| 国产91丝袜在线播放0| 99色视频在线观看| 国产麻豆精品免费视频| 精品久久久久久中文| 亚飞与亚基在线观看| 久久久成人网| 国产欧美精品午夜在线播放| 99热视热频这里只有精品| 高清一级做a爱过程不卡视频| 一级片免费在线观看视频| 国产成a人片在线观看视频| 日韩免费片| 国产精品1024永久免费视频| 久久精品免视看国产明星| 欧美a级v片不卡在线观看| 国产精品免费久久| 日本特黄特色aaa大片免费| 精品久久久久久影院免费| 欧美激情伊人| 久久国产精品自线拍免费| 91麻豆爱豆果冻天美星空| 欧美大片a一级毛片视频| 久久国产精品自由自在| 精品国产一区二区三区免费| 日韩欧美一二三区| 国产一区免费观看| 国产综合成人观看在线| 四虎影视精品永久免费网站| 一本高清在线| 青青久热| 精品视频在线观看视频免费视频| 成人免费观看视频| 色综合久久天天综合观看| 国产网站免费视频| 国产国语对白一级毛片| 999精品视频在线|