亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Golang > 正文

Go語言中的內存布局詳解

2020-04-01 19:07:58
字體:
來源:轉載
供稿:網友

一、go語言內存布局

想象一下,你有一個如下的結構體。

 

復制代碼 代碼如下:

type MyData struct {
        aByte   byte
        aShort  int16
        anInt32 int32
        aSlice  []byte
}

 

那么這個結構體究竟是什么呢? 從根本上說,它描述了如何在內存中布局數據。 這是什么意思?編譯器又是如何展現出來呢? 我們來看一下。 首先讓我們使用反射來檢查結構中的字段。

二、反射之上

下面是一些使用反射來找出字段大小及其偏移量(它們相對于結構的開始位于內存中的位置)的代碼。 反射可以告訴我們編譯器是怎么看待類型(包括結構)的。

 

復制代碼 代碼如下:

// First ask Go to give us some information about the MyData type
typ := reflect.TypeOf(MyData{})
fmt.Printf("Struct is %d bytes long/n", typ.Size())
// We can run through the fields in the structure in order
n := typ.NumField()
for i := 0; i < n; i++ {
        field := typ.Field(i)
        fmt.Printf("%s at offset %v, size=%d, align=%d/n",
            field.Name, field.Offset, field.Type.Size(),
            field.Type.Align())
 }

 

除了每個字段的偏移和大小,我還打印了每個字段的對齊方式,我稍后會解釋。結果如下:

 

復制代碼 代碼如下:

Struct is 32 bytes long
aByte at offset 0, size=1, align=1
aShort at offset 2, size=2, align=2
anInt32 at offset 4, size=4, align=4
aSlice at offset 8, size=24, align=8

 

aByte是我們結構體中的第一個字段,偏移量為0.它使用1字節的內存。

aShort是第二個字段。它使用2字節的內存。奇怪的是偏移量是2。這是為什么呢?答案是對齊, CPU更好地訪問位于2字節(“2字節邊界”)的倍數的地址處的2個字節,并訪問位于4字節邊界上的4個字節,直到CPU的自然整數大小,在現代CPU上是8字節(64位)。

在一些較舊的RISC CPU訪問錯誤對齊的數字引起一個故障:在一些UNIX系統上,這將是一個SIGBUS,它會停止你的程序(或內核)。一些系統能夠處理這些錯誤并修復錯誤:您的代碼將運行,但會緩慢的運行,因為額外的代碼將由操作系統運行以修復錯誤。我相信英特爾和ARM的CPU也只是處理芯片上的任何不對齊:也許我們將在以后的文章中測試這一點,以及任何性能的影響。

無論如何,對齊是Go編譯器跳過一個字節放置字段aShort以便它位于2字節邊界的原因。因為這樣,我們可以將另一個字段放進結構體中,而不使它占用更大內存。這里是我們的結構的新版本,在aByte之后立即有一個新字段anotherByte。

 

復制代碼 代碼如下:

type MyData struct {
       aByte       byte
       anotherByte byte
       aShort      int16
       anInt32     int32
       aSlice      []byte
}

 

我們再次運行反射代碼,可以看到anotherByte正好在aByte和aShort之間的空閑空間。 它坐落在偏移1,aShort仍然在偏移2.現在可能是時候注意我之前提到的那個神秘對齊字段。 它告訴我們和Go編譯器,這個字段需要如何對齊。

 

復制代碼 代碼如下:

Struct is 32 bytes long
aByte at offset 0, size=1, align=1
anotherByte at offset 1, size=1, align=1
aShort at offset 2, size=2, align=2
anInt32 at offset 4, size=4, align=4
aSlice at offset 8, size=24, align=8

 

三、看看內存

然而我們的結構體在內存中到底是什么樣子? 讓我們看看我們能不能找到答案。 首先讓我們構建一個MyData實例,并填充一些值。我選擇了應該容易在內存中找到的值。

 

復制代碼 代碼如下:

data := MyData{
        aByte:   0x1,
        aShort:  0x0203,
        anInt32: 0x04050607,
        aSlice:  []byte{
                0x08, 0x09, 0x0a,
        },
 }

 

現在一些代碼訪問組成這個結構的字節。 我們想要獲取這個結構的實例,在內存中找到它的地址,并打印出該內存中的字節。

我們使用unsafe包來幫助我們這樣做。 這讓我們繞過Go類型系統將指向我們的結構的指針轉換為32字節數組,這個數組就是組成我們的結構體的內存數據。

 

復制代碼 代碼如下:

dataBytes := (*[32]byte)(unsafe.Pointer(&data))
fmt.Printf("Bytes are %#v/n", dataBytes)

 

我們運行以上代碼。 這是結果,第一個字段,aByte,從我們的結構中以粗體顯示。 這是希望你期望的,單字節aByte = 0x01在偏移0。

 

復制代碼 代碼如下:

Bytes are &[32]uint8{**0x1**, 0x0, 0x3, 0x2, 0x7, 0x6, 0x5, 0x4, 0x5a, 0x5, 0x1, 0x20, 0xc4, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}

 

接下來我們來看看AShort。 這是在偏移量2的位置并且長度為2.如果你記得,aShort = 0x0203,但數據顯示的字節是倒序。 這是因為大多數現代CPU都是Little-Endian:該值的最低位字節首先出現在內存中。

 

復制代碼 代碼如下:

Bytes are &[32]uint8{0x1, 0x0, **0x3, 0x2**, 0x7, 0x6, 0x5, 0x4, 0x5a, 0x5, 0x1, 0x20, 0xc4, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}

 

同樣的事情發生在Int32 = 0x04050607。 最低位字節首先出現在內存中。

 

復制代碼 代碼如下:

Bytes are &[32]uint8{0x1, 0x0, 0x3, 0x2, **0x7, 0x6, 0x5, 0x4**, 0x5a, 0x5, 0x1, 0x20, 0xc4, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}

 

四、神秘的插曲

現在我們看到什么? 這是aSlice = [] byte {0x08,0x09,0x0a} ,在偏移量8的24個字節。我沒有看到我的序列0x08,0x09,0x0a的任何地方的任何符號。 這是怎么回事?

 

復制代碼 代碼如下:

Bytes are &[32]uint8{0x1, 0x0, 0x3, 0x2, 0x7, 0x6, 0x5, 0x4, **0x5a, 0x5, 0x1, 0x20, 0xc4, 0x0, 0x0, 0x0, 0x3, 0x0**, **0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0**}

 

Go反射包里自有答案。 slice在Go語言中由以下結構體表示,該結構從指針數據開始,該數據指向保存切片中的數據的存儲器; 然后是該存儲器中的有用數據的長度Len,以及該存儲器的大小Cap。

 

復制代碼 代碼如下:

type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
}

 

如果把它提供給我們的代碼,我們得到以下偏移和大小。 數據指針和兩個長度各為8個字節,具有8個字節對齊。

 

復制代碼 代碼如下:

Struct is 24 bytes long
Data at offset 0, size=8, align=8
Len at offset 8, size=8, align=8
Cap at offset 16, size=8, align=8

 

如果我們再看一下后面的內存結構,我們可以看到數據是在地址0x000000c42001055a。 之后,我們看到Len和Cap都是3,這是我們的數據的長度。

 

復制代碼 代碼如下:

Bytes are &[32]uint8{0x1, 0x0, 0x3, 0x2, 0x7, 0x6, 0x5, 0x4, **0x5a, 0x5, 0x1, 0x20, 0xc4, 0x0, 0x0, 0x0**, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}

 

我們可以直接用以下代碼訪問這些數據字節。 首先讓我們直接訪問slice頭,然后打印出數據指向的內存。

 

復制代碼 代碼如下:

dataslice := *(*reflect.SliceHeader)(unsafe.Pointer(&data.aSlice))
fmt.Printf("Slice data is %#v/n",
        (*[3]byte)(unsafe.Pointer(dataslice.Data)))

 

這是輸出:

 

復制代碼 代碼如下:

Slice data is &[3]uint8{0x8, 0x9, 0xa}

 

總結

以上就是關于Go語言內存布局的全部內容了,希望本文的內容對大家學習或者使用Go語言能有所幫助,如果有疑問大家可以留言交流。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美丰满老妇厨房牲生活| 国产精品96久久久久久| 亚洲成人久久电影| 久久久久久久国产精品| 欧美激情a∨在线视频播放| 久久精品国产2020观看福利| 久久精品一本久久99精品| 7777精品视频| 亚洲精品美女久久久久| 国产视频久久久久| 91香蕉嫩草神马影院在线观看| 海角国产乱辈乱精品视频| 久久资源免费视频| 5566成人精品视频免费| 亚洲乱码国产乱码精品精天堂| 97久久久免费福利网址| 日韩精品中文字幕有码专区| 久久综合九色九九| 成人在线视频网| 国产精品久久久久久久av电影| 亚洲人午夜色婷婷| 精品丝袜一区二区三区| 在线电影欧美日韩一区二区私密| 岛国av一区二区三区| www.欧美视频| 成人日韩在线电影| 亚洲在线视频观看| 欧美日韩美女视频| 91干在线观看| 久久精品国产99国产精品澳门| 亚洲激情视频在线| 亚洲美女在线视频| 日韩在线免费视频观看| 欧美激情影音先锋| 97久久国产精品| 亚洲伊人久久综合| 国产xxx69麻豆国语对白| 亚洲欧美国产一区二区三区| 日韩网站免费观看| 一个人看的www欧美| 国产一区av在线| 欧美激情在线一区| 久久97精品久久久久久久不卡| 欧美另类第一页| 日韩成人av在线| 久久亚洲精品一区| 久久中文精品视频| 日韩精品在线视频| 亚洲高清免费观看高清完整版| 一区二区三区美女xx视频| 91系列在线观看| 欧美专区日韩视频| 亚洲成人精品av| 久久久www成人免费精品张筱雨| 亚洲欧美综合区自拍另类| 26uuu日韩精品一区二区| 日韩av电影手机在线| 亚洲综合最新在线| 91精品国产自产在线老师啪| 欧洲亚洲妇女av| 波霸ol色综合久久| 欧美激情亚洲另类| 欧美国产日本高清在线| 日本不卡视频在线播放| 亚洲黄在线观看| 国产色婷婷国产综合在线理论片a| 日韩中文字幕在线视频| 黑人欧美xxxx| 中文字幕精品—区二区| 51色欧美片视频在线观看| 国产精品7m视频| 国产精品国产三级国产专播精品人| 亚洲女人天堂av| 91久久久亚洲精品| 日韩精品在线电影| 国产精品99久久久久久www| 国产精品激情av在线播放| 欧洲午夜精品久久久| 欧美精品激情blacked18| 草民午夜欧美限制a级福利片| 一区二区三区天堂av| 欧美国产精品人人做人人爱| 久久九九全国免费精品观看| 国产欧美精品久久久| 欧美成人全部免费| 亚洲一区二区免费在线| 4p变态网欧美系列| 亚洲天堂av电影| 亚洲成人在线视频播放| 成人精品久久久| 在线看日韩欧美| 日本不卡免费高清视频| 精品色蜜蜜精品视频在线观看| 亚洲欧美资源在线| 日韩经典第一页| 亚洲高清色综合| 国产亚洲欧美另类中文| 精品久久久久久久中文字幕| 国产亚洲精品久久久久久牛牛| 久久影院资源网| 欧美日韩第一视频| 亚洲伦理中文字幕| 狠狠躁天天躁日日躁欧美| 欧美黄色小视频| 亚洲精品美女在线观看| 国产欧美精品一区二区三区-老狼| 久久的精品视频| 91在线观看免费网站| 国产亚洲精品va在线观看| 欧美日韩爱爱视频| 欧美日韩亚洲成人| 国产精品444| 俺去了亚洲欧美日韩| 国产精品一区二区久久久| 欧美激情精品久久久久久大尺度| 亚洲区免费影片| www.欧美精品一二三区| 欧美色视频日本高清在线观看| 中文字幕国产精品| 欧美国产日韩一区二区| 欧美猛交免费看| 日韩免费观看视频| 国产女精品视频网站免费| 欧美激情一级精品国产| 北条麻妃一区二区在线观看| 欧美孕妇孕交黑巨大网站| 亚洲欧美精品一区| 亚洲男人av电影| 中文字幕成人精品久久不卡| 欧美激情在线视频二区| 国产成一区二区| 亚洲性69xxxbbb| 色综合久久88色综合天天看泰| 国产a∨精品一区二区三区不卡| 97久久超碰福利国产精品…| 91精品在线影院| 亚洲石原莉奈一区二区在线观看| 国产成人精品最新| 美女福利视频一区| 亚州欧美日韩中文视频| 法国裸体一区二区| 久久久视频免费观看| 国产香蕉一区二区三区在线视频| 国产精品日韩电影| 蜜月aⅴ免费一区二区三区| 亚洲第一精品自拍| 91成人国产在线观看| 成人国产精品色哟哟| 国产精品18久久久久久麻辣| 成人欧美一区二区三区在线| 性欧美长视频免费观看不卡| 国产一区二区视频在线观看| 日韩一区二区三区xxxx| 亚洲精品xxxx| 久久久久久久久久久免费| 91夜夜揉人人捏人人添红杏| 亚洲精品av在线播放| 国产精品久久二区| 91丨九色丨国产在线| 亚洲黄色免费三级| 久久久99免费视频| 欧美一级片免费在线| 国产网站欧美日韩免费精品在线观看| 欧美超级乱淫片喷水|