国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - 關于Go 空結構體的 3 種使用場景

關于Go 空結構體的 3 種使用場景

2021-11-22 10:39煎魚eddycjy Golang

在今天這篇文章要給大家介紹得是Go 語言中幾種常見類型的寬度,并且基于開頭的問題 ”空結構體“ 進行了剖析,需要的朋友可以參考一下,希望對你有所幫助

前言:

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

?
1
ch := make(chan struct{})

還清一色的使用結構體,也不用其他類型。高度常見,也就不是一個偶發現象了,肯定是背后必然有什么原因。

1、為什么使用

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

關于Go 空結構體的 3 種使用場景

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

?
1
2
3
4
5
6
7
// 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

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

我們對應看看 Go 語言中幾種常見的類型寬度大小:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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),
 )
}

輸出結果:

8 16 1 12 24 8

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

2、空結構體的特殊性

空結構體在各類系統中頻繁出現的原因之一,就是需要一個占位符。而恰恰好,Go 空結構體的寬度是特殊的。
如下:

?
1
2
3
4
func main() {
 var s struct{}
 fmt.Println(unsafe.Sizeof(s))
}

輸出結果:

0

空結構體的寬度是很直接了當的 0,即便是變形處理:

?
1
2
3
4
5
6
7
8
9
type S struct {
 A struct{}
 B struct{}
}
 
func main() {
 var s S
 fmt.Println(unsafe.Sizeof(s))
}

其最終輸出結果也是 0,完美切合人們對占位符的基本訴求,就是占著坑位,滿足基本輸入輸出就好。
但這時候問題又出現了,為什么只有空結構會有這種特殊待遇,其他類型又不行?
這是 Go 編譯器在內存分配時做的優化項

?
1
2
3
4
5
6
7
8
9
// 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)
 }
}

當發現 size 為 0 時,會直接返回變量 zerobase 的引用,該變量是所有 0 字節的基準地址,不占據任何寬度。
因此空結構體的廣泛使用,是 Go 開發者們借助了這個小優化,達到了占位符的目的。

3、使用場景

了解清楚為什么空結構作為占位符使用的原因后,我們更進一步了解其真實的使用場景有哪些。

主要分為三塊:

  • 實現方法接收者。
  • 實現集合類型。
  • 實現空通道。

3.1 實現方法接收者

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

?
1
2
3
type T string
 
func (s *T) Call()

又似乎有點不大友好,因為作為一個字符串類型,其本身會占據定的空間。
這種時候我們會采用空結構體的方式,這樣也便于未來針對該類型進行公共字段等的增加。如下:

?
1
2
3
4
5
6
7
8
9
10
type T struct{}
 
func (s *T) Call() {
 fmt.Println("腦子進煎魚了")
}
 
func main() {
 var s T
 s.Call()
}

在該場景下,使用空結構體從多維度來考量是最合適的,易拓展,省空間,最結構化。
另外你會發現,其實你在日常開發中下意識就已經這么做了,你可以理解為設計模式和日常生活相結合的另類案例。

3.2 實現集合類型

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

這就是空結構體大戰身手的場景了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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("煎魚"))
}

空結構體作為占位符,不會額外增加不必要的內存開銷,很方便的就是解決了。

3.3 實現空通道

Go channel 的使用場景中,常常會遇到通知型 channel,其不需要發送任何數據,只是用于協調 Goroutine 的運行,用于流轉各類狀態或是控制并發情況。
如下:

?
1
2
3
4
5
6
7
8
9
10
11
func main() {
 ch := make(chan struct{})
 go func() {
  time.Sleep(1 * time.Second)
  close(ch)
 }()
 
 fmt.Println("腦子好像進...")
 <-ch
 fmt.Println("煎魚了!")
}

輸出結果:

腦子好像進...
煎魚了!

該程序會先輸出 ”腦子好像進...“ 后,再睡眠一段時間再輸出 "煎魚了!",達到間斷控制 channel 的效果。
由于該 channel 使用的是空結構體,因此也不會帶來額外的內存開銷。

到此這篇關于關于Go 空結構體的 3 種使用場景的文章就介紹到這了,更多相關Go 空結構體的 3 種使用場景內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://juejin.cn/post/7018037514246029349

延伸 · 閱讀

精彩推薦
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網11352020-05-21
  • Golanggolang的httpserver優雅重啟方法詳解

    golang的httpserver優雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • Golanggolang json.Marshal 特殊html字符被轉義的解決方法

    golang json.Marshal 特殊html字符被轉義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • GolangGolang通脈之數據類型詳情

    Golang通脈之數據類型詳情

    這篇文章主要介紹了Golang通脈之數據類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數名等等,Go語言中標識符允許由...

    4272021-11-24
  • GolangGolang中Bit數組的實現方式

    Golang中Bit數組的實現方式

    這篇文章主要介紹了Golang中Bit數組的實現方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • Golanggo日志系統logrus顯示文件和行號的操作

    go日志系統logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
主站蜘蛛池模板: 亚洲欧美综合乱码精品成人网 | 亚洲福利一区二区 | 亚洲日本韩国在线观看 | 日本久草 | 成人免费xxx在线观看 | 日韩高清国产一区在线 | 特污影院 | 久久国产精品无码网站 | 亚洲欧美精品一区二区三区 | 国产成人三区 | 免费观看黄视频 | www.久久久 | 免费在线观看一区二区三区 | 久草热8精品视频在线观看 久久亚洲精品中文字幕 | 国产精品无码永久免费888 | av一区二区三区四区 | 亚洲国产精品成人精品 | 电影在线观看免费 | 欧美国产日韩视频 | 成人精品网站在线观看 | 免费久草| 久久久久久久久久久九 | 亚洲国产区 | 成人aaaa免费全部观看 | 国产一区二区视频免费看 | 国产第一区在线观看 | 五月天婷婷免费视频 | 成人高清视频在线观看 | xxxx网| 转生成为史莱姆这档事第四季在线观看 | 91精品一区二区 | 亚洲专区欧美 | 精品久久久久久久久久久久 | 亚洲在线电影 | 亚洲欧美高清 | 亚洲国产成人精品女 | 欧美一区国产一区 | 青草福利| 日韩欧美国产一区二区 | 国产精品色一区二区三区 | 香蕉成人啪国产精品视频综合网 |