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

一文帶你搞懂Golang結(jié)構(gòu)體內(nèi)存布局

 更新時間:2022年10月20日 08:58:53   作者:1個俗人  
結(jié)構(gòu)體在Go語言中是一個很重要的部分,在項目中會經(jīng)常用到。這篇文章主要帶大家看一下結(jié)構(gòu)體在內(nèi)存中是怎么分布的?通過對內(nèi)存布局的了解,可以幫助我們寫出更優(yōu)質(zhì)的代碼。感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助

前言

結(jié)構(gòu)體在Go語言中是一個很重要的部分,在項目中會經(jīng)常用到,大家在寫Go時有沒有注意過,一個struct所占的空間不一定等于各個字段加起來的空間之和,甚至有時候把字段的順序調(diào)整一下,struct的所占空間不一樣,接下來通過這篇文章來看一下結(jié)構(gòu)體在內(nèi)存中是怎么分布的?通過對內(nèi)存布局的了解,可以幫助我們寫出更優(yōu)質(zhì)的代碼。感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

結(jié)構(gòu)體內(nèi)存布局

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

結(jié)構(gòu)體實際上就是由各種類型的數(shù)據(jù)組合而成的一種符合數(shù)據(jù)類型,一個結(jié)構(gòu)體變量的大小是由結(jié)構(gòu)體中的字段決定。結(jié)構(gòu)體和它所包含的數(shù)據(jù)在內(nèi)存中是以連續(xù)塊的形式存在的。我們可以借助unsafe.Sizeof方法,來獲?。?/p>

package main

import (
	"fmt"
	"unsafe"
)

type Test struct {
	T1 int8 // 1
	T2 int8 // 1
	T3 int8 // 1
}
func main() {
    var t Test
	fmt.Println(unsafe.Sizeof(t)) //3 bytes

}

內(nèi)存對齊

不同類型的變量占用內(nèi)存大小是不一樣的,但是cpu每次讀取的內(nèi)存長度是固定的(比如cpu是64位的,一次可以從內(nèi)存中讀取64位的數(shù)據(jù),即8個字節(jié)),為了cpu能高效的讀寫數(shù)據(jù),編譯器會把各種類型的數(shù)據(jù)放在合適的地址,而不是順序的一個接一個的排放,并占用合適的長度,這就是內(nèi)存對齊。每種類型的對齊值就是它的對齊邊界。

示例:

package main

import (
	"fmt"
	"unsafe"
)
type Test struct {
	a int8 // 1
	b int64 // 8
	c int32 // 4
}
type Test2 struct {
	a int8 // 1
	b int32 // 4
	c int64 // 8
}
func main() {
    var t Test
	fmt.Println(unsafe.Sizeof(t)) // 24
	var t2 Test2
	fmt.Println(unsafe.Sizeof(t2))// 16
}

通過上面示例,我們可以看到兩個結(jié)構(gòu)體中3個字段類型相同,當(dāng)排列順序發(fā)生變化時,總的內(nèi)存大小也會發(fā)生變化。下面我們來一起分析一下:

如果沒有內(nèi)存對齊,那結(jié)構(gòu)體各個字段在內(nèi)存中是緊密排列的,如t1內(nèi)存布局示意圖如下:

因為b這個字段需要8個字節(jié),所以會有一個字節(jié)的數(shù)據(jù)排列到第2個字中。如果程序想要讀取b字段的數(shù)據(jù),那么CPU需要兩次讀取才能獲取到完整的數(shù)據(jù),這樣就會影響了程序的性能。

所以,為了能讓CPU減少一次獲取的時間,Go編譯器會幫你把struct結(jié)構(gòu)體做數(shù)據(jù)的對齊,以便CPU可以一次將該數(shù)據(jù)從內(nèi)存中讀取出來。重新排列后內(nèi)存布局結(jié)構(gòu)示意圖如下:

其中有13個字節(jié)是真正存儲數(shù)據(jù)的,而灰色的11個字節(jié)則是為了對齊而填充上的,不存儲任何數(shù)據(jù),所以才會比沒有對齊排列時多出11個字節(jié)。

雖然通過對齊填充的方式提高了CPU讀寫數(shù)據(jù)的效率,但是這些填充內(nèi)存確實有點(diǎn)浪費(fèi)空間,那有沒有辦法既可以既可以做到內(nèi)存對齊保證CPU讀寫效率又能減少浪費(fèi)內(nèi)存空間呢?

那就是調(diào)整struct字段的順序,我們在來看一下t2結(jié)構(gòu)體的字段內(nèi)存布局結(jié)構(gòu)示意圖如下:

這樣重新排列后,只占了16個字節(jié),比上面那種方式少了8個字節(jié)。由此可知,對結(jié)構(gòu)體字段的重新排列會讓結(jié)構(gòu)體更節(jié)省內(nèi)。

總結(jié)

本篇文章我們一起學(xué)習(xí)了Go 語言中的內(nèi)存對齊,主要內(nèi)容如下:

  • 結(jié)構(gòu)體是占用一塊連續(xù)的內(nèi)存,一個結(jié)構(gòu)體變量的大小是由結(jié)構(gòu)體中的字段決定。
  • unsafe.Sizeof(x) 返回了變量x的內(nèi)存占用大小。
  • 兩個結(jié)構(gòu)體,即使包含變量類型的數(shù)量相同,但是位置不同,占用的內(nèi)存大小也不同,由此引出了內(nèi)存對齊。
  • 對結(jié)構(gòu)體字段的重新排列會讓結(jié)構(gòu)體更節(jié)省內(nèi)。

到此這篇關(guān)于一文帶你搞懂Golang結(jié)構(gòu)體內(nèi)存布局的文章就介紹到這了,更多相關(guān)Golang結(jié)構(gòu)體內(nèi)存布局內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言中的變量聲明和賦值

    Go語言中的變量聲明和賦值

    這篇文章主要介紹了Go語言中的變量聲明和賦值的方法,十分的細(xì)致全面,有需要的小伙伴可以參考下。
    2015-04-04
  • Golang中Set類型的實現(xiàn)方法示例詳解

    Golang中Set類型的實現(xiàn)方法示例詳解

    這篇文章主要給大家介紹了關(guān)于Golang中Set類型實現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • GoFrame 框架緩存查詢結(jié)果的示例詳解

    GoFrame 框架緩存查詢結(jié)果的示例詳解

    GoFrame的gdb對查詢結(jié)果的緩存處理是不是非常的優(yōu)雅。尤其是*gcache.Cache對象采用了適配器設(shè)計模式,可以輕松實現(xiàn)從單進(jìn)程內(nèi)存緩存切換為分布式的Redis緩存,本文重點(diǎn)給大家介紹GoFrame 如何優(yōu)雅的緩存查詢結(jié)果,感興趣的朋友一起看看吧
    2022-06-06
  • golang xorm日志寫入文件中的操作

    golang xorm日志寫入文件中的操作

    這篇文章主要介紹了golang xorm日志寫入文件中的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang你一定要懂的連接池實現(xiàn)

    Golang你一定要懂的連接池實現(xiàn)

    這篇文章主要介紹了Golang你一定要懂的連接池實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 一文徹底理解Golang閉包實現(xiàn)原理

    一文徹底理解Golang閉包實現(xiàn)原理

    閉包對于一個長期寫Java的開發(fā)者來說估計鮮有耳聞,光這名字感覺就有點(diǎn)"神秘莫測"。這篇文章的主要目的就是從編譯器的角度來分析閉包,徹底搞懂閉包的實現(xiàn)原理,需要的可以參考一下
    2022-10-10
  • go build和go install的區(qū)別介紹

    go build和go install的區(qū)別介紹

    這篇文章主要介紹了go build和go install的區(qū)別介紹,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go 1.22中的for循環(huán)新特性詳解

    Go 1.22中的for循環(huán)新特性詳解

    在 Go 語言中,for 循環(huán)是實現(xiàn)迭代的主要方式,Go 中的 for 循環(huán)非常靈活,有多種使用方式,本文將給大家詳細(xì)的介紹一下Go 1.22中的for循環(huán)新特性,感興趣的朋友可以參考下
    2024-02-02
  • Go語言實現(xiàn)本地緩存的策略詳解

    Go語言實現(xiàn)本地緩存的策略詳解

    今天給大家分享的是Go語言本地緩存的一些內(nèi)容,主要是結(jié)合bigcache和fastcache兩個優(yōu)秀的開源代碼庫,總結(jié)一些設(shè)計思路和感悟,文章通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Golang 限流器的使用和實現(xiàn)示例

    Golang 限流器的使用和實現(xiàn)示例

    這篇文章主要介紹了Golang 限流器的使用和實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06

最新評論