欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

golang低級(jí)編程:一.unsafe包

go語(yǔ)言在設(shè)計(jì)上確保了一些安全的屬性,限制了程序可能出錯(cuò)的途徑。例如嚴(yán)格的類型轉(zhuǎn)換規(guī)則。但也使得很多實(shí)現(xiàn)的細(xì)節(jié)無(wú)法通過(guò)go程序來(lái)訪問(wèn),例如對(duì)于聚合類型(如結(jié)構(gòu)體)的內(nèi)存布局,或者一個(gè)函數(shù)對(duì)應(yīng)的機(jī)器碼。

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、重慶小程序開(kāi)發(fā)公司、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了汕尾免費(fèi)建站歡迎大家使用!

這里我們將討論unsafe包,它是由編譯器實(shí)現(xiàn)的,實(shí)現(xiàn)了對(duì)語(yǔ)言內(nèi)置特性的訪問(wèn)功能,這些特性一般是不可見(jiàn)的,因?yàn)樗鼈儽┞读薵o詳細(xì)的內(nèi)存布局。雖然包的名字叫unsafe,但是這些函數(shù)本身是安全的,并且在做內(nèi)存優(yōu)化的時(shí)候,它們對(duì)理解函數(shù)底層內(nèi)存布局很有幫助。

unsafe.Sizeof

unsafe.Sizeof 報(bào)告?zhèn)鬟f給它的參數(shù)在內(nèi)存中所占的字節(jié)長(zhǎng)度,這個(gè)參數(shù)可以是任意類型的表達(dá)式。Sizeof僅會(huì)報(bào)告每個(gè)數(shù)據(jù)結(jié)構(gòu)固定部分的內(nèi)存所占字節(jié)長(zhǎng)度,例如指針或者字符串所占的長(zhǎng)度,但不會(huì)報(bào)告例如字符串內(nèi)容的間接長(zhǎng)度。為了可移植性,以字來(lái)表示引用類型的長(zhǎng)度或者包含引用類型的長(zhǎng)度,在32位系統(tǒng)上字的長(zhǎng)度是4個(gè)字節(jié),而在64位系統(tǒng)上字的長(zhǎng)度是8個(gè)字節(jié)。

package main

import (
	"fmt"
	"unsafe"
)

func main() {
	var x struct{
		a bool
		b int16
		c []int
	}

	fmt.Println(unsafe.Sizeof(x.a))
	fmt.Println(unsafe.Sizeof(x.b))
	fmt.Println(unsafe.Sizeof(x.c))
	fmt.Println(unsafe.Sizeof(x))
}
// 64位機(jī)器結(jié)果:
// 1  : 1個(gè)字節(jié),bool
// 2  : 兩個(gè)字節(jié),16/8 = 2
// 24 : 切片24個(gè)字節(jié),3個(gè)字,因?yàn)榍衅粋€(gè)指針,一個(gè)長(zhǎng)度,一個(gè)容量。
// 32 :前面兩個(gè)加上內(nèi)存空位后就是一個(gè)字,8個(gè)字節(jié)。所以 8 + 24 = 32

如果b和c交換位置,那么內(nèi)存空位將會(huì)更大,8 + 24 + 8 = 40

func main() {
	var x struct{
		a bool
		c []int
		b int16
	}

	fmt.Println(unsafe.Sizeof(x.a))
	fmt.Println(unsafe.Sizeof(x.c))
	fmt.Println(unsafe.Sizeof(x.b))
	fmt.Println(unsafe.Sizeof(x))
}
// 64位機(jī)器結(jié)果:
// 1
// 24
// 2
// 40   這里8 + 24 = 32和我們的猜想一樣。

unsafe.Alignof

unsafe.Alignof報(bào)告參數(shù)類型所要求的對(duì)齊方式。這個(gè)參數(shù)可以是任意類型的表達(dá)式,并返回一個(gè)常量。布爾類型和數(shù)值類型對(duì)齊到它們的長(zhǎng)度(最大8個(gè)字節(jié)),其他類型按字對(duì)齊。

package main

import (
	"fmt"
	"unsafe"
)

func main() {
	var x struct{
		a bool
		b int16
		c []int
	}

	fmt.Println(unsafe.Alignof(x.a))
	fmt.Println(unsafe.Alignof(x.b))
	fmt.Println(unsafe.Alignof(x.c))
	fmt.Println(unsafe.Alignof(x))
}

// 64位機(jī)器結(jié)果:
// 1  :這是布爾類型,布爾類型和數(shù)值類型對(duì)齊到它們長(zhǎng)度
// 2  :這里數(shù)值類型,同上
// 8  :其他類型按字對(duì)齊,在64位機(jī)器上,一個(gè)字是8個(gè)字節(jié)
// 8

unsafe.Offsetof(f)

計(jì)算成員f相對(duì)于結(jié)構(gòu)體的起始地址的偏移量。如果有內(nèi)存空位也計(jì)算在內(nèi),該函數(shù)的操作數(shù),必須是一個(gè)成員選擇器:x.a。

func main() {
	var x struct{
		a bool
		c []int
		b int16
	}

	fmt.Println(unsafe.Offsetof(x.a))
	fmt.Println(unsafe.Offsetof(x.c))
	fmt.Println(unsafe.Offsetof(x.b))
}
// 64位機(jī)器結(jié)果:
// 0 : 結(jié)構(gòu)體的第一個(gè)成員
// 8 :這里有7個(gè)字節(jié)的內(nèi)存空位
// 32

unsafe.Pointer

unsafe.Pointer是一種特殊類型的指針,它可以存儲(chǔ)任何變量的地址。對(duì)于一個(gè)unsafe.Pointer類型的指針,由于我們不知道它的具體類型,導(dǎo)致我們不能間接的通過(guò)*p來(lái)獲取它的實(shí)際值。普通類型的指針也可以轉(zhuǎn)換為unsafe.Pointer類型的指針,unsafe.Pointer類型的指針可以轉(zhuǎn)換為普通類型的指針,而且不必和原來(lái)的類型相同。使用unsafe.Pointer進(jìn)行類型轉(zhuǎn)換可以將任意的值寫入內(nèi)存,并因此破壞類型系統(tǒng)。

uintper類型

uintper類型保存了指針?biāo)赶虻刂返臄?shù)值,這樣就可以進(jìn)行數(shù)值運(yùn)算。(uintpter類型是一個(gè)足夠大的無(wú)符號(hào)整型,可以用來(lái)表示任何地址。)unsafe.Pointer也可以轉(zhuǎn)換為uintptr,當(dāng)然uintptr也可以轉(zhuǎn)換為unsafe.Pointer(這里也會(huì)破壞類型系統(tǒng))。

package main

import (
	"fmt"
	"unsafe"
)

func main() {
	var x struct{
		a bool
		b int16
		c []int
	}

	//pb := &x.b
	pb := (*int16)(unsafe.Pointer(uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b)))

	*pb = 42
	fmt.Println(x.b)
}

這里首先將x的地址轉(zhuǎn)換為unsafe.Pointer類型從而轉(zhuǎn)換為uintptr類型,uintptr類型就可以用于計(jì)算。計(jì)算后再轉(zhuǎn)換為原來(lái)的類型,對(duì)內(nèi)存地址指向的區(qū)域賦值。但是這里不能引入uintptr類型的臨時(shí)變量,例如下面這樣。因?yàn)槔厥掌鲿?huì)移動(dòng)內(nèi)存中的變量,為了減少內(nèi)存碎片。但是在垃圾回收器uintptr類型僅僅是一個(gè)數(shù)值,所以移動(dòng)過(guò)后,不會(huì)改變uintptr存的指針對(duì)應(yīng)的內(nèi)存里的數(shù)據(jù)。

    ptr := uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b)
    pb := (*int16)(unsafe.Pointer(ptr))

總結(jié)

unsafe包可以用來(lái)操作內(nèi)存,從而增加go語(yǔ)言的靈活性,但是unsafe包無(wú)法保證在未來(lái)go語(yǔ)言升級(jí)中能夠兼容。uintptr類型不能作為臨時(shí)變量。并且在uintptr類型轉(zhuǎn)換到unsafe.Pointer的過(guò)程中要盡量減少uintptr的操作次數(shù)。

當(dāng)前標(biāo)題:golang低級(jí)編程:一.unsafe包
文章出自:http://chinadenli.net/article6/dsoisig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、網(wǎng)站內(nèi)鏈、外貿(mào)建站、網(wǎng)站設(shè)計(jì)公司、網(wǎng)站排名、企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)