成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

理解Go中空結構體的應用和實現原理

開發 前端
空結構體是一種不包含任何字段的結構體類型,不僅具有結構體類型的一切屬性,而且該結構體類型占用的空間為0。常被用于map的集合或和通道配合使用發送信號使用的場景。

在實際項目或開源程序中,相信大家都見過將一個空結構體作為map值的場景:

// CanSkipFuncs will skip valid if RequiredFirst is true and the struct field's value is empty
var CanSkipFuncs = map[string]struct{}{
    "Email":   {},
    "IP":      {},
    "Mobile":  {},
    "Tel":     {},
    "Phone":   {},
    "ZipCode": {},
}

或將一個空結構體寫入到通道中的使用:

w.ch <- struct{}{}

那為什么要這樣使用空結構體呢?今天就跟大家一起來學習下空結構體的應用以及底層原理。

1 什么空結構體

首先來看看空結構體是什么??战Y構體也是結構體類型,具有結構體的一切特性。但該結構體中沒有任何字段組合。所以,該空結構體類型的變量占用的空間為0。

我們通過unsafe.Sizeof函數來驗證一下。unsafe.Sizeof函數的作用是返回一個數據類型所占的空間大小。我們驗證一下:

var s struct{}
fmt.Println(unsafe.Sizeof(s)) // prints 0

我們看到打印的結果是0,表明struct{}的類型占用的空間是0。

我們還可以通過reflect的類型來驗證。

var s struct{}
typ := reflect.TypeOf(s)
fmt.Println(typ.Size()) // 0

我們看到,通過映射變量s的類型,輸出空類型的空間大小也是0。

2 空結構體類型變量的地址

我們知道,在編程語言中,變量的作用就是在內存中,標記和存儲數據的。也就是說每個變量會對應著一塊內存空間,既然是內存空間,那就應該有對應的內存地址。那空結構體類型變量的地址是什么呢?我們通過如下代碼來看下:

package main
 
import (
    "fmt"
    "unsafe"
)
 
type emptyStruct struct{}
 
func main() {
    a := struct{}{}
    b := struct{}{}
 
    c := emptyStruct{}
 
    fmt.Println(a)
    fmt.Printf("%pn", &a) //0x116be80
    fmt.Printf("%pn", &b) //0x116be80
    fmt.Printf("%pn", &c) //0x116be80
 
    fmt.Println(a == b) //true
}

我們發現,所有空結構體類型的變量地址都是一樣的。那這是為什么呢?

在底層實現中,這和一個很重要的 zerobase 變量有關(在runtime里多次使用到了這個變量),而zerobase 變量是一個 uintptr 的全局變量,占用8個字節。在go源碼src/runtime/malloc.go中有如下定義:

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

只要你將struct{} 賦值給一個或者多個變量,它都返回這個 zerobase 的地址,這點我們上面已經證實過這一點了。

在golang中大量的地方使用到了這個 zerobase 變量,只要分配的內存為0,就返回這個變量地址,在go源碼src/runtime/malloc.go的mallocgc函數中定義如下:

func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
    if gcphase == _GCmarktermination {
  throw("mallocgc called with gcphase == _GCmarktermination")
    }


    if size == 0 {
  return unsafe.Pointer(&zerobase)
    }
    ...
}

3 空結構體的應用場景

一般我們用在用戶不關注值內容的情況下,只是作為一個信號或一個占位符來使用。

  • 基于map實現集合功能。
  • 與channel組合使用,實現一個信號

基于map實現集合功能就是我們開頭提到的。使用空結構體不占用存儲空間外,還有一個語義上的原因。例如:

var CanSkipFuncs = map[string]bool{
    "Email":   true,
    "IP":      true,
    "Mobile":  true,
    "Tel":     false,
    "Phone":   false,
    "ZipCode": false,
}

我們這里將空結構體類型更換成布爾類型。首先,聲明下,CanSkipFuncs集合代表的是所有要跳過的函數。所以這里的值設置成true還是false是沒有任何影響的。

那么當閱讀或review代碼的時候,很有可能帶來疑惑,對于值所表達的意圖就有所懷疑,增加了理解代碼的難度。就會理解成當值為true時會執行一個分支,當值為false時會執行另一段邏輯。而相比使用一個空結構體strcut{}理解起來會更容易,一看空結構體struct{}就知道要表達的意思是不需要關心值是什么,只需要關心鍵值即可。

我們再來看下和channel組合使用的例子。在etcd項目中,就有通過往channel中寫入一個空結構體作為信號的,源碼位于/etcd/server/auth/simple_token.go中,如下:

func (tm *simpleTokenTTLKeeper) stop() {
    select {
    case tm.stopc <- struct{}{}:
    case <-tm.donec:
    }
    <-tm.donec
}

還有一種是基于緩沖channel實現并發限速。如下:

var limit = make(chan struct{}, 3)


func main() {
    // …………
    for _, w := range work {
        go func() {
            limit <- struct{}{}
            w()
            <-limit
        }()
    }
    // …………
}

4 總結

空結構體是一種不包含任何字段的結構體類型,不僅具有結構體類型的一切屬性,而且該結構體類型占用的空間為0。常被用于map的集合或和通道配合使用發送信號使用的場景。

參考鏈接:

https://blog.haohtml.com/archives/20339

https://ijayer.github.io/post/tech/code/golang/20200419_emtpy_struct_in_go/

責任編輯:武曉燕 來源: 大話開源
相關推薦

2021-11-02 12:19:18

Go函數結構

2020-12-02 09:10:22

Go結構數據類型

2023-07-29 15:03:29

2021-04-20 09:00:48

Go 語言結構體type

2024-08-14 18:18:47

2021-11-02 14:54:41

Go結構體標簽

2023-11-21 08:03:43

語言架構偏移量

2020-08-10 15:24:05

Snowflake算法開源

2020-12-02 08:45:36

Go語言

2020-11-30 06:17:03

Go語言

2020-11-26 06:40:24

Go語言基礎

2022-10-24 00:48:58

Go語言errgroup

2009-08-13 14:24:44

C#結構體構造函數

2020-11-23 08:54:14

Go語言結構體

2021-12-20 07:59:07

Go語言結構體

2022-05-06 09:22:25

Go泛型

2022-07-06 08:30:36

vuereactvdom

2024-01-02 10:54:07

Rust結構體元組

2011-04-11 13:00:08

C++結構體枚舉

2020-07-21 15:20:20

語言結構體共用體
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久精品国产清自在天天线 | 综合国产 | 欧美在线一区二区三区 | 欧美日一区二区 | 人人玩人人添人人澡欧美 | 伊人色综合久久天天五月婷 | 久久青视频 | 91资源在线 | 精产国产伦理一二三区 | 精品毛片 | 精品美女视频在线观看免费软件 | 国产精品国产精品国产专区不片 | 久久久91精品国产一区二区三区 | 国产高清视频一区 | 国产成人jvid在线播放 | 特一级毛片 | 午夜激情在线 | 亚洲天堂中文字幕 | 日韩在线观看视频一区 | 日韩人体视频 | 羞羞在线观看视频 | 一区二区三区四区视频 | xx视频在线 | 精品三级在线观看 | 国产成人精品视频 | av一区二区三区四区 | 一区二区三区四区免费在线观看 | 日韩喷潮| 亚洲国产一区二区视频 | 久久综合九九 | 视频一区二区三区中文字幕 | 精品欧美一区二区在线观看 | 国产精品日韩欧美一区二区三区 | 久久手机在线视频 | av一区二区三区四区 | 黄视频在线网站 | 国产福利小视频 | 国产精品18hdxxxⅹ在线 | 国内精品视频一区二区三区 | 久久久久久免费毛片精品 | 欧美日韩久久 |