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

關(guān)于Go 空結(jié)構(gòu)體的 3 種使用場景

 更新時(shí)間:2021年10月21日 16:22:22   作者:煎魚eddycjy  
在今天這篇文章要給大家介紹得是Go 語言中幾種常見類型的寬度,并且基于開頭的問題 ”空結(jié)構(gòu)體“ 進(jìn)行了剖析,需要的朋友可以參考一下,希望對(duì)你有所幫助

前言:

在 Go 語言中,有一個(gè)比較特殊的類型,經(jīng)常會(huì)有剛接觸 Go 的小伙伴問到,又或是不理解。
他就是 Go 里的空結(jié)構(gòu)體(struct)的使用,常常會(huì)有看到有人使用:

ch := make(chan struct{})

還清一色的使用結(jié)構(gòu)體,也不用其他類型。高度常見,也就不是一個(gè)偶發(fā)現(xiàn)象了,肯定是背后必然有什么原因。

1、為什么使用

說白了,就是希望節(jié)省空間。但,新問題又來了,為什么不能用其他的類型來做?

這就涉及到在 Go 語言中 ”寬度“ 的概念,寬度描述了一個(gè)類型的實(shí)例所占用的存儲(chǔ)空間的字節(jié)數(shù)。
寬度是一個(gè)類型的屬性。在 Go 語言中的每個(gè)值都有一個(gè)類型,值的寬度由其類型定義,并且總是 8 bits 的倍數(shù)。
在 Go 語言中我們可以借助 unsafe.Sizeof 方法,來獲?。?br />

// Sizeof takes an expression x of any type and returns the size in bytes
// of a hypothetical variable v as if v was declared via var v = x.
// The size does not include any memory possibly referenced by x.
// For instance, if x is a slice, Sizeof returns the size of the slice
// descriptor, not the size of the memory referenced by the slice.
// The return value of Sizeof is a Go constant.
func Sizeof(x ArbitraryType) uintptr

該方法能夠得到值的寬度,自然而然也就能知道其類型對(duì)應(yīng)的寬度是多少了。

我們對(duì)應(yīng)看看 Go 語言中幾種常見的類型寬度大?。?/strong>

func main() {
 var a int
 var b string
 var c bool
 var d [3]int32
 var e []string
 var f map[string]bool

 fmt.Println(
  unsafe.Sizeof(a),
  unsafe.Sizeof(b),
  unsafe.Sizeof(c),
  unsafe.Sizeof(d),
  unsafe.Sizeof(e),
  unsafe.Sizeof(f),
 )
}

輸出結(jié)果:

8 16 1 12 24 8

你可以發(fā)現(xiàn)我們列舉的幾種類型,只是單純聲明,我們也啥沒干,依然占據(jù)一定的寬度。
如果我們的場景,只是占位符,那怎么辦,系統(tǒng)里的開銷就這么白白浪費(fèi)了?

2、空結(jié)構(gòu)體的特殊性

空結(jié)構(gòu)體在各類系統(tǒng)中頻繁出現(xiàn)的原因之一,就是需要一個(gè)占位符。而恰恰好,Go 空結(jié)構(gòu)體的寬度是特殊的。
如下:

func main() {
 var s struct{}
 fmt.Println(unsafe.Sizeof(s))
}

輸出結(jié)果:

0

空結(jié)構(gòu)體的寬度是很直接了當(dāng)?shù)?0,即便是變形處理:

type S struct {
 A struct{}
 B struct{}
}

func main() {
 var s S
 fmt.Println(unsafe.Sizeof(s))
}

其最終輸出結(jié)果也是 0,完美切合人們對(duì)占位符的基本訴求,就是占著坑位,滿足基本輸入輸出就好。
但這時(shí)候問題又出現(xiàn)了,為什么只有空結(jié)構(gòu)會(huì)有這種特殊待遇,其他類型又不行?
這是 Go 編譯器在內(nèi)存分配時(shí)做的優(yōu)化項(xiàng)

// base address for all 0-byte allocations
var zerobase uintptr

func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
 ...
 if size == 0 {
  return unsafe.Pointer(&zerobase)
 }
}

當(dāng)發(fā)現(xiàn) size 為 0 時(shí),會(huì)直接返回變量 zerobase 的引用,該變量是所有 0 字節(jié)的基準(zhǔn)地址,不占據(jù)任何寬度。
因此空結(jié)構(gòu)體的廣泛使用,是 Go 開發(fā)者們借助了這個(gè)小優(yōu)化,達(dá)到了占位符的目的。

3、使用場景

了解清楚為什么空結(jié)構(gòu)作為占位符使用的原因后,我們更進(jìn)一步了解其真實(shí)的使用場景有哪些。

主要分為三塊:

  • 實(shí)現(xiàn)方法接收者。
  • 實(shí)現(xiàn)集合類型。
  • 實(shí)現(xiàn)空通道。

3.1 實(shí)現(xiàn)方法接收者

在業(yè)務(wù)場景下,我們需要將方法組合起來,代表其是一個(gè) ”分組“ 的,便于后續(xù)拓展和維護(hù)。
但是如果我們使用:

type T string

func (s *T) Call()

又似乎有點(diǎn)不大友好,因?yàn)樽鳛橐粋€(gè)字符串類型,其本身會(huì)占據(jù)定的空間。
這種時(shí)候我們會(huì)采用空結(jié)構(gòu)體的方式,這樣也便于未來針對(duì)該類型進(jìn)行公共字段等的增加。如下:

type T struct{}

func (s *T) Call() {
 fmt.Println("腦子進(jìn)煎魚了")
}

func main() {
 var s T
 s.Call()
}

在該場景下,使用空結(jié)構(gòu)體從多維度來考量是最合適的,易拓展,省空間,最結(jié)構(gòu)化。
另外你會(huì)發(fā)現(xiàn),其實(shí)你在日常開發(fā)中下意識(shí)就已經(jīng)這么做了,你可以理解為設(shè)計(jì)模式和日常生活相結(jié)合的另類案例。

3.2 實(shí)現(xiàn)集合類型

在 Go 語言的標(biāo)準(zhǔn)庫中并沒有提供集合(Set)的相關(guān)實(shí)現(xiàn),因此一般在代碼中我們圖方便,會(huì)直接用 map 來替代。
但有個(gè)問題,就是集合類型的使用,只需要用到 key(鍵),不需要 value(值)。

這就是空結(jié)構(gòu)體大戰(zhàn)身手的場景了:

type Set map[string]struct{}

func (s Set) Append(k string) {
 s[k] = struct{}{}
}

func (s Set) Remove(k string) {
 delete(s, k)
}

func (s Set) Exist(k string) bool {
 _, ok := s[k]
 return ok
}

func main() {
 set := Set{}
 set.Append("煎魚")
 set.Append("咸魚")
 set.Append("蒸魚")
 set.Remove("煎魚")

 fmt.Println(set.Exist("煎魚"))
}

空結(jié)構(gòu)體作為占位符,不會(huì)額外增加不必要的內(nèi)存開銷,很方便的就是解決了。

3.3 實(shí)現(xiàn)空通道

Go channel 的使用場景中,常常會(huì)遇到通知型 channel,其不需要發(fā)送任何數(shù)據(jù),只是用于協(xié)調(diào) Goroutine 的運(yùn)行,用于流轉(zhuǎn)各類狀態(tài)或是控制并發(fā)情況。
如下:

func main() {
 ch := make(chan struct{})
 go func() {
  time.Sleep(1 * time.Second)
  close(ch)
 }()

 fmt.Println("腦子好像進(jìn)...")
 <-ch
 fmt.Println("煎魚了!")
}

輸出結(jié)果:

腦子好像進(jìn)...
煎魚了!

該程序會(huì)先輸出 ”腦子好像進(jìn)...“ 后,再睡眠一段時(shí)間再輸出 "煎魚了!",達(dá)到間斷控制 channel 的效果。
由于該 channel 使用的是空結(jié)構(gòu)體,因此也不會(huì)帶來額外的內(nèi)存開銷。

到此這篇關(guān)于關(guān)于Go 空結(jié)構(gòu)體的 3 種使用場景的文章就介紹到這了,更多相關(guān)Go 空結(jié)構(gòu)體的 3 種使用場景內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言的方法接受者類型用值類型還是指針類型?

    Go語言的方法接受者類型用值類型還是指針類型?

    這篇文章主要介紹了Go語言的方法接受者類型用值類型還是指針類型?本文還同時(shí)講解了關(guān)于接受者的命名方式,需要的朋友可以參考下
    2014-10-10
  • GO語言字符串處理Strings包的函數(shù)使用示例講解

    GO語言字符串處理Strings包的函數(shù)使用示例講解

    這篇文章主要為大家介紹了GO語言字符串處理Strings包的函數(shù)使用示例講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Golang設(shè)計(jì)模式之外觀模式講解和代碼示例

    Golang設(shè)計(jì)模式之外觀模式講解和代碼示例

    外觀是一種結(jié)構(gòu)型設(shè)計(jì)模式, 能為復(fù)雜系統(tǒng)、 程序庫或框架提供一個(gè)簡單 (但有限) 的接口,這篇文章就給大家詳細(xì)介紹一下Golang的外觀模式,文中有詳細(xì)的代碼示例,具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-06-06
  • 深入探究Golang中flag標(biāo)準(zhǔn)庫的使用

    深入探究Golang中flag標(biāo)準(zhǔn)庫的使用

    在本文中,我們將深入探討 flag 標(biāo)準(zhǔn)庫的實(shí)現(xiàn)原理和使用技巧,以幫助讀者更好地理解和掌握該庫的使用方法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-04-04
  • 深入淺出Golang中的sync.Pool

    深入淺出Golang中的sync.Pool

    sync.Pool是可伸縮的,也是并發(fā)安全的,其大小僅受限于內(nèi)存大小。本文主要為大家介紹一下Golang中sync.Pool的原理與使用,感興趣的小伙伴可以了解一下
    2023-03-03
  • Go 代碼規(guī)范錯(cuò)誤處理示例經(jīng)驗(yàn)總結(jié)

    Go 代碼規(guī)范錯(cuò)誤處理示例經(jīng)驗(yàn)總結(jié)

    這篇文章主要為大家介紹了Go 代碼規(guī)范錯(cuò)誤處理示例實(shí)戰(zhàn)經(jīng)驗(yàn)總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Go并發(fā)之RWMutex的源碼解析詳解

    Go并發(fā)之RWMutex的源碼解析詳解

    RWMutex是一個(gè)支持并行讀串行寫的讀寫鎖。RWMutex具有寫操作優(yōu)先的特點(diǎn),寫操作發(fā)生時(shí),僅允許正在執(zhí)行的讀操作執(zhí)行,后續(xù)的讀操作都會(huì)被阻塞。本文就來從源碼解析一下RWMutex的使用
    2023-03-03
  • 在Mac OS上安裝Go語言編譯器的方法

    在Mac OS上安裝Go語言編譯器的方法

    這篇文章主要介紹了在Mac OS上安裝Go語言編譯器的方法,Docker的興起使得Go近來人氣大幅攀升,需要的朋友可以參考下
    2015-10-10
  • Go實(shí)現(xiàn)Redis連接池方法

    Go實(shí)現(xiàn)Redis連接池方法

    為了更深入了解golang連接池的實(shí)現(xiàn),自已又重寫了一遍連接池。文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Go語言操作mysql數(shù)據(jù)庫簡單例子

    Go語言操作mysql數(shù)據(jù)庫簡單例子

    這篇文章主要介紹了Go語言操作mysql數(shù)據(jù)庫簡單例子,本文包含插入數(shù)據(jù)和查詢代碼實(shí)例,需要的朋友可以參考下
    2014-10-10

最新評(píng)論

杨浦区| 岳西县| 贵州省| 泽普县| 鹤庆县| 金门县| 务川| 怀安县| 平定县| 木兰县| 增城市| 武汉市| 日照市| 连州市| 龙里县| 宜昌市| 广元市| 潞西市| 安仁县| 姚安县| 清苑县| 景东| 社会| 栖霞市| 建德市| 花莲县| 临夏县| 曲水县| 济南市| 中西区| 瓦房店市| 巴马| 鲁山县| 龙陵县| 九龙县| 杨浦区| 舞钢市| 兖州市| 湄潭县| 扎赉特旗| 舟曲县|