最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang內(nèi)存對(duì)齊詳解

 更新時(shí)間:2023年10月16日 08:51:58   作者:寫代碼的lorre  
在golang中,每一種數(shù)據(jù)類型都有其對(duì)應(yīng)的數(shù)據(jù)類型大小,也就是占用了多少內(nèi)存空間,我們可以通過unsafe.Sizeof函數(shù),來確定一個(gè)變量占用的內(nèi)存字節(jié)數(shù),本文將詳細(xì)給大家介紹golang內(nèi)存對(duì)齊,需要的朋友可以參考下

背景

在golang中,每一種數(shù)據(jù)類型都有其對(duì)應(yīng)的數(shù)據(jù)類型大小,也就是占用了多少內(nèi)存空間

我們可以通過unsafe.Sizeof函數(shù),來確定一個(gè)變量占用的內(nèi)存字節(jié)數(shù)

demo:

package main
import (
   "fmt"
   "testing"
   "unsafe"
)
func TestTypeSize(t *testing.T) {
   var a int8 = 4
   s1 := "hello world"
   s2 := "hahaha"
   fmt.Println(unsafe.Sizeof(a))  // 1字節(jié)
   fmt.Println(unsafe.Sizeof(s1)) // 16字節(jié)
   fmt.Println(unsafe.Sizeof(s2)) // 16字節(jié)
}

注意:

  • unsafe.Sizeof返回的是一個(gè)變量占用的內(nèi)存字節(jié)數(shù),而不是變量所表示內(nèi)容占用的內(nèi)存字節(jié)數(shù)。所以在上述demo中,盡管s1和s2的字符串內(nèi)容不一樣,但s1和s2的變量類型都是string,所以s1和s2占用的內(nèi)存字節(jié)數(shù)相同

結(jié)構(gòu)體大小

我們還可以通過unsafe.Sizeof來獲取結(jié)構(gòu)體占用的內(nèi)存字節(jié)數(shù)

demo1:

package main
import (
   "fmt"
   "testing"
   "unsafe"
)
type demo1 struct {
   a int8
   b int16
}
func TestStructSize1(t *testing.T) {
   d1 := demo1{}
   fmt.Println(unsafe.Sizeof(d1.a)) // 1字節(jié)
   fmt.Println(unsafe.Sizeof(d1.b)) // 2字節(jié)
   fmt.Println(unsafe.Sizeof(d1))   // 4字節(jié)
}

問題1:

  • 結(jié)構(gòu)體占用的內(nèi)存字節(jié)數(shù)不等于結(jié)構(gòu)體內(nèi)各個(gè)字段占用的內(nèi)存字節(jié)數(shù)之和。結(jié)構(gòu)體內(nèi)各個(gè)字段占用的內(nèi)存字節(jié)數(shù)之和為:3字節(jié) = 1字節(jié)(a占用字節(jié)數(shù)) + 2字節(jié)(b占用字節(jié)數(shù)),結(jié)構(gòu)體占用字節(jié)數(shù)為4字節(jié)

demo2:

package main
import (
   "fmt"
   "testing"
   "unsafe"
)
type demo2 struct {
   a int8
   b int16
   c int32
   d int64
}
type demo3 struct {
   a int8
   d int64
   b int16
   c int32
}
func TestStructSize2(t *testing.T) {
   d2 := demo2{}
   fmt.Println(unsafe.Sizeof(d2.a)) // 1字節(jié)
   fmt.Println(unsafe.Sizeof(d2.b)) // 2字節(jié)
   fmt.Println(unsafe.Sizeof(d2.c)) // 4字節(jié)
   fmt.Println(unsafe.Sizeof(d2.d)) // 8字節(jié)
   fmt.Println(unsafe.Sizeof(d2))   // 16字節(jié)
   d3 := demo3{}
   fmt.Println(unsafe.Sizeof(d3.a)) // 1字節(jié)
   fmt.Println(unsafe.Sizeof(d3.b)) // 2字節(jié)
   fmt.Println(unsafe.Sizeof(d3.c)) // 4字節(jié)
   fmt.Println(unsafe.Sizeof(d3.d)) // 8字節(jié)
   fmt.Println(unsafe.Sizeof(d3))   // 24字節(jié)
}

問題2:

  • 當(dāng)兩個(gè)結(jié)構(gòu)體內(nèi)的字段類型一樣時(shí),字段順序不同時(shí),結(jié)構(gòu)體占用的字節(jié)數(shù)也可能不同

出現(xiàn)上面兩個(gè)問題的根本原因,就是本文要討論的內(nèi)容:內(nèi)存對(duì)齊

什么是內(nèi)存對(duì)齊

現(xiàn)代計(jì)算機(jī)中內(nèi)存空間都是按照byte劃分的,從理論上講似乎對(duì)任何類型的變量的訪問可以從任何地址開始,但實(shí)際情況是在訪問特定變量的時(shí)候經(jīng)常在特定的內(nèi)存地址訪問,這就需要各類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序的一個(gè)接一個(gè)的排放,這就是對(duì)齊

簡(jiǎn)單來說,內(nèi)存對(duì)齊就是把各種數(shù)據(jù)類型按照一定的規(guī)則,在內(nèi)存空間進(jìn)行排列,而不是直接按照順序進(jìn)行排列

為什么需要內(nèi)存對(duì)齊

那么為什么需要進(jìn)行內(nèi)存對(duì)齊呢,主要原因有以下幾點(diǎn):

  • 性能原因:CPU為了加速對(duì)內(nèi)存的訪問速度,并不是一個(gè)字節(jié)一個(gè)字節(jié)的去訪問內(nèi)存,而是一次訪問多個(gè)字節(jié),一般稱之為字長(zhǎng)。32位CUP的字長(zhǎng)一般是4字節(jié),64位CPU的字長(zhǎng)一般是8字節(jié)。如果沒有進(jìn)行內(nèi)存對(duì)齊,那么CPU在訪問一個(gè)變量時(shí),可能需要進(jìn)行多次讀取,然后進(jìn)行拼接,才能得到最終的變量?jī)?nèi)容。進(jìn)行內(nèi)存對(duì)齊后,可以減少CPU訪問內(nèi)存次數(shù),提升性能

  • 更好的保證訪問的原子性

  • 平臺(tái)原因(移植原因):不是所有的硬件平臺(tái)都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺(tái)只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常

如何進(jìn)行內(nèi)存對(duì)齊

常見數(shù)據(jù)類型的內(nèi)存對(duì)齊

編譯器按照每種數(shù)據(jù)類型的對(duì)齊邊界來進(jìn)行內(nèi)存對(duì)齊

首先需要確認(rèn)每種數(shù)據(jù)類型的對(duì)齊邊界,對(duì)齊邊界 = min(類型大小,平臺(tái)字長(zhǎng))

常見數(shù)據(jù)類型在常見平臺(tái)上的對(duì)齊邊界:

類型類型大小64位平臺(tái)字長(zhǎng)64位平臺(tái)對(duì)齊邊界32位平臺(tái)字長(zhǎng)32位平臺(tái)對(duì)齊邊界
int81byte8byte1byte4byte1byte
int162byte8byte2byte4byte2byte
int324byte8byte4byte4byte4byte
int648byte8byte8byte4byte4byte
string16byte8byte8byte4byte4byte

為什么對(duì)齊邊界需要取類型大小和平臺(tái)字長(zhǎng)的最小值呢?

答案是為了節(jié)省內(nèi)存,避免內(nèi)存浪費(fèi),提升讀取的性能

  • 當(dāng)類型大小 < 平臺(tái)字長(zhǎng)時(shí),int8類型在64位平臺(tái)進(jìn)行內(nèi)存對(duì)齊兩種情況如圖:

  • 當(dāng)類型大小 > 平臺(tái)字長(zhǎng)時(shí),int64類型在32位平臺(tái)進(jìn)行內(nèi)存對(duì)齊兩種情況如圖:

結(jié)構(gòu)體的內(nèi)存對(duì)齊

結(jié)構(gòu)體的對(duì)齊邊界為:結(jié)構(gòu)體內(nèi)成員類型最大的對(duì)齊邊界

結(jié)構(gòu)體進(jìn)行內(nèi)存對(duì)齊的兩個(gè)要求:

  • 起始地址是結(jié)構(gòu)體對(duì)齊邊界的倍數(shù)
  • 結(jié)構(gòu)體整體占用字節(jié)數(shù)必須是結(jié)構(gòu)體對(duì)齊邊界的倍數(shù)。為了保證結(jié)構(gòu)體數(shù)組的內(nèi)存對(duì)齊

下面我們具體分析下結(jié)構(gòu)體的內(nèi)存對(duì)齊

type demo4 struct {
   a int8
   b int64
   c int32
   d int16
}

首先確定結(jié)構(gòu)體demo4的對(duì)齊邊界為:成員類型最大的對(duì)齊邊界 = 8byte

結(jié)構(gòu)體內(nèi)存對(duì)齊如圖:

結(jié)構(gòu)體內(nèi)存對(duì)齊的特殊情況

如果結(jié)構(gòu)體的字段包含空結(jié)構(gòu)體類型時(shí)

  • 空結(jié)構(gòu)體類型字段不是最后一個(gè)字段時(shí),不會(huì)占用內(nèi)存
  • 空結(jié)構(gòu)體類型字段是最后一個(gè)字段時(shí),需要進(jìn)行內(nèi)存對(duì)齊,占用的內(nèi)存大小和前一個(gè)字段的大小一致

demo:

package main
import (
   "fmt"
   "testing"
   "unsafe"
)
type demo5 struct {
   s struct{}
   a int8
}
type demo6 struct {
   a int8
   s struct{}
}
func TestStructSize3(t *testing.T) {
   d5 := demo5{}
   fmt.Println(unsafe.Sizeof(d5.a)) // 1字節(jié)
   fmt.Println(unsafe.Sizeof(d5.s)) // 0字節(jié)
   fmt.Println(unsafe.Sizeof(d5))   // 1字節(jié)
   d6 := demo6{}
   fmt.Println(unsafe.Sizeof(d6.a)) // 1字節(jié)
   fmt.Println(unsafe.Sizeof(d6.s)) // 0字節(jié)
   fmt.Println(unsafe.Sizeof(d6))   // 2字節(jié)
}

空結(jié)構(gòu)體類型字段是最后一個(gè)字段時(shí),需要占用內(nèi)存,主要還是為了解決內(nèi)存泄漏問題

內(nèi)存泄漏問題分析:

以上就是golang內(nèi)存對(duì)齊詳解的詳細(xì)內(nèi)容,更多關(guān)于golang內(nèi)存對(duì)齊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語言入門Go?Web?Fiber框架快速了解

    Go語言入門Go?Web?Fiber框架快速了解

    這篇文章主要為大家介紹了Go語言入門Go?Web?Fiber框架的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • GoLang string與strings.Builder使用對(duì)比詳解

    GoLang string與strings.Builder使用對(duì)比詳解

    這篇文章主要介紹了GoLang string與strings.Builder使用對(duì)比,Builder 用于使用 Write 方法有效地構(gòu)建字符串。它最大限度地減少了內(nèi)存復(fù)制。零值可以使用了。不要復(fù)制非零生成器
    2023-03-03
  • Go語言web框架Gin響應(yīng)客戶端的方式

    Go語言web框架Gin響應(yīng)客戶端的方式

    Gin是一個(gè)用Go語言編寫的web框架,它是一個(gè)類似于martini但擁有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍,本文給大家介紹了Go語言web框架Gin響應(yīng)客戶端有哪些方式,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下
    2024-10-10
  • 在Golang中實(shí)現(xiàn)定時(shí)任務(wù)的幾種高效方法

    在Golang中實(shí)現(xiàn)定時(shí)任務(wù)的幾種高效方法

    本文將詳細(xì)介紹在Golang中實(shí)現(xiàn)定時(shí)任務(wù)的幾種高效方法,包括time包中的Ticker和Timer、第三方庫(kù)cron的使用,以及基于channel和goroutine的自定義實(shí)現(xiàn),我們將通過實(shí)際代碼示例和性能分析,幫助開發(fā)者選擇最適合自己場(chǎng)景的定時(shí)任務(wù)解決方案,需要的朋友可以參考下
    2025-06-06
  • go語言奇偶轉(zhuǎn)置排序算法實(shí)現(xiàn)方法(附帶源碼)

    go語言奇偶轉(zhuǎn)置排序算法實(shí)現(xiàn)方法(附帶源碼)

    這篇文章主要介紹了go語言奇偶轉(zhuǎn)置排序算法實(shí)現(xiàn)方法的相關(guān)資料,這種算法是一種專門為并行計(jì)算環(huán)境設(shè)計(jì)的排序算法,它通過交替執(zhí)行奇數(shù)索引和偶數(shù)索引的比較來排序,需要的朋友可以參考下
    2026-02-02
  • go語言開發(fā)中如何優(yōu)雅得關(guān)閉協(xié)程方法

    go語言開發(fā)中如何優(yōu)雅得關(guān)閉協(xié)程方法

    這篇文章主要為大家介紹了go語言開發(fā)中如何優(yōu)雅得關(guān)閉協(xié)程方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • golang獲取客戶端ip的實(shí)現(xiàn)

    golang獲取客戶端ip的實(shí)現(xiàn)

    本文主要介紹了golang獲取客戶端ip的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Golang中間件設(shè)計(jì)示例詳解

    Golang中間件設(shè)計(jì)示例詳解

    這篇文章主要介紹了Golang中間件設(shè)計(jì)示例,中間件是在HTTP請(qǐng)求處理過程中,對(duì)請(qǐng)求進(jìn)行處理的一種模式,中間件可以在請(qǐng)求到達(dá)處理器之前或之后對(duì)請(qǐng)求進(jìn)行攔截,修改或者增強(qiáng),同時(shí)可以對(duì)響應(yīng)進(jìn)行處理,需要的朋友可以參考下
    2023-05-05
  • 詳解如何在golang鏡像中設(shè)置指定時(shí)區(qū)

    詳解如何在golang鏡像中設(shè)置指定時(shí)區(qū)

    這篇文章主要為大家詳細(xì)介紹了如何在golang鏡像中設(shè)置指定時(shí)區(qū),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的可以了解一下
    2023-04-04
  • 總結(jié)Golang四種不同的參數(shù)配置方式

    總結(jié)Golang四種不同的參數(shù)配置方式

    這篇文章主要介紹了總結(jié)Golang四種不同的參數(shù)配置方式,文章圍繞主題展開詳細(xì)的內(nèi)容戒殺,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09

最新評(píng)論

松桃| 汤阴县| 海兴县| 凤翔县| 库伦旗| 越西县| 怀集县| 右玉县| 昭觉县| 邢台市| 津市市| 罗山县| 东兰县| 项城市| 耿马| 潮州市| 泰州市| 会同县| 石嘴山市| 宾阳县| 垦利县| 广汉市| 油尖旺区| 综艺| 星子县| 禹州市| 临清市| 尉氏县| 景德镇市| 桦川县| 磐安县| 永昌县| 故城县| 锦州市| 兴文县| 和平区| 合肥市| 禹州市| 平果县| 庆安县| 砀山县|