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

Gopher 需要知道的幾個結構體騷操作

開發 后端
我們知道 Go 沒有繼承的概念,接口結構體多使用組合,很多開源產品或是源代碼都有大量的內嵌 (embeded field) 字段,用于特殊目的。

[[440247]]

本文轉載自微信公眾號「董澤潤的技術筆記」,作者董澤潤。轉載本文請聯系董澤潤的技術筆記公眾號。

我們知道 Go 沒有繼承的概念,接口結構體多使用組合,很多開源產品或是源代碼都有大量的內嵌 (embeded field) 字段,用于特殊目的

NoCopy

  1. package main 
  2.  
  3. import ( 
  4.  "sync" 
  5.  
  6. func test(wg sync.WaitGroup) { 
  7.  defer wg.Done() 
  8.  wg.Add(1) 
  9.  
  10. func main() { 
  11.  var wg sync.WaitGroup 
  12.  wg.Add(1) 
  13.  go test(wg) 
  14.  wg.Wait() 

這是非常經典的 case, 程序執行報錯 all goroutines are asleep - deadlock!, 解決也很簡單,把 wg 由值傳遞變成指針類型即可。本質是 WaitGroup 內部維護了計數,不允許 copy 變量,還有 sync.Mutex 鎖也是不允許 copy 的

解決辦法很簡單,需要 CI 時由 linter 檢測出來,最好運行時也能有檢測機制,這方面的討論請參考issue 8005[1]

  1. zerun.dong$ go vet aaa.go 
  2. # command-line-arguments 
  3. ./aaa.go:7:14: test passes lock by value: sync.WaitGroup contains sync.noCopy 
  4. ./aaa.go:15:10: call of test copies lock value: sync.WaitGroup contains sync.noCopy 

這是 go vet 結果,報錯己經很明顯了

  1. type noCopy struct{} 

noCopy 定義非常簡單,空結構體,zero size 不占用空間(前提是非結構體的最后一個字段,否則還要是有 8 byte 空間開銷)

sync.WaitGroup[2] 內嵌 noCopy 字段,防止 Cond 變量被復制

  1. type WaitGroup struct { 
  2.  noCopy noCopy 
  3.  
  4.  // 64-bit value: high 32 bits are counter, low 32 bits are waiter count
  5.  // 64-bit atomic operations require 64-bit alignment, but 32-bit 
  6.  // compilers only guarantee that 64-bit fields are 32-bit aligned. 
  7.  // For this reason on 32 bit architectures we need to check in state() 
  8.  // if state1 is aligned or notand dynamically "swap" the field order if 
  9.  // needed. 
  10.  state1 uint64 
  11.  state2 uint32 

上面是 sync.WaitGroup 結構體的定義,同時注意 noCopy 是源碼中不可導出的定義。如果用戶代碼也想實現 NoCopy 呢?可以參考 grpc DoNotCopy[3]

  1. // DoNotCopy can be embedded in a struct to help prevent shallow copies. 
  2. // This does not rely on a Go language feature, but rather a special case 
  3. // within the vet checker. 
  4. type DoNotCopy [0]sync.Mutex 

非常簡單,Mutex 零長數組,不占用空間。由于 vet checker 會檢測 Mutex,相當于替我們實現了 noCopy 功能

DoNotCompare

Golang Sepc Comparison_operators[4] 官方文檔描述常見類型比較運算( == != > < <= >=)的結果,詳細內容看官方文檔 https://go.dev/ref/spec#Comparison_operators

  • In any comparison, the first operand must be assignable to the type of the second operand, or vice versa.
  • The equality operators == and != apply to operands that are comparable. The ordering operators <, <=, >, and >= apply to operands that are ordered.
  • Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
  • Slice, map, and function values are not comparable. However, as a special case, a slice, map, or function value may be compared to the predeclared identifier nil. Comparison of pointer, channel, and interface values to nil is also allowed and follows from the general rules above.

對于 struct 來講,只有所有字段全部 comparable 的(不限大小寫是否導出),那么結構體才可以比較。同時只比較 non-blank 的字段,舉個例子:

  1. type T struct { 
  2.     name string 
  3.     age int 
  4.     _ float64 
  5. func main() { 
  6.    x := [...]float64{1.1, 2, 3.14} 
  7.    fmt.Println(x == [...]float64{1.1, 2, 3.14}) // true 
  8.    y := [1]T{{"foo", 1, 0}} 
  9.    fmt.Println(y == [1]T{{"foo", 1, 1}}) // true 

運行后,結果均為 true

Slice, Map, Function 均是不可比較的,只與判斷是否為 nil. 所以我們可以利用這兩個特性,內嵌函數來實現不可比較,參考 protobuf DoNotCompare[5]

  1. // DoNotCompare can be embedded in a struct to prevent comparability. 
  2. type DoNotCompare [0]func() 

如果比較會報錯

  1. type DoNotCompare [0]func() 
  2.  
  3. type T struct { 
  4.     name string 
  5.     age int 
  6.     DoNotCompare 
  7. func main() { 
  8. // ./cmp.go:13:21: invalid operation: T{} == T{} (struct containing DoNotCompare cannot be compared) 
  9.     fmt.Println(T{} == T{}) 

NoUnkeyedLiterals

結構體初始化有兩種:指定字段名稱,或者按順序列出所有字段,不指定名稱

  1. type User struct{ 
  2.     Age int 
  3.     Address string 
  4.  
  5. u := &User{21, "beijing"

這樣寫的問題非常大,如果新增字段會不兼容

  1. type User struct{ 
  2.     Age int 
  3.     Address string 
  4.     Money int 
  5.  
  6. func main(){ 
  7. // ./struct.go:11:15: too few values in User{...} 
  8.   _ = &User{21, "beijing"

上面的例子,能在編譯期報錯還是可接受的,如果同類型的調換順序,那才叫坑爹... 所以這時需要 NoUnkeyedLiterals[6]

  1. // NoUnkeyedLiterals can be embedded in a struct to prevent unkeyed literals. 
  2. type NoUnkeyedLiterals struct{} 

很簡單,就是一個空結構體,這是 Protobuf 的實現。很多時候我們都用空的結構體占位符實現

  1. type User struct{ 
  2.     _ struct{} 
  3.     Age int 
  4.     Address string 
  5.  
  6. func main(){ 
  7. // ./struct.go:10:11: cannot use 21 (type intas type struct {} in field value 
  8. // ./struct.go:10:15: cannot use "beijing" (type untyped string) as type int in field value 
  9. // ./struct.go:10:15: too few values in User{...} 
  10. _ = &User{21, "beijing"

報錯很明顯了,字段類型不匹配,有人會說初始化寫上 struct{} 不就可以了?

  1. _ = &User{struct{}{}, 21, "beijing"

這樣確實可以工作,但是占位符 _ 的字段是不可導出的,所以 import 其它包的 NoUnkeyedLiterals 結構體同樣會報錯

Copier 庫

最后推薦一個非常實用的 copier[7] 庫,CRUD Boy 經常結構體轉來轉去的,比如 dto, dao 互轉,或是 dao 與其它互轉,如果修改了 dao 結構體,還要記得修改其它轉換邏輯,非常繁瑣

  1. package main 
  2. import ( 
  3.   "fmt" 
  4.   "github.com/jinzhu/copier" 
  5.  
  6. type User struct { 
  7.   Name string 
  8.   Age  int 
  9.  
  10. type Employee struct { 
  11.   Name string 
  12.   Age  int 
  13.   Role string 
  14.  
  15. func main() { 
  16.   user := User{Name"dj", Age: 18} 
  17.   employee := Employee{Role: "admin"
  18.  
  19.   copier.Copy(&employee, &user
  20.   // main.Employee{Name:"dj", Age:18, Role:"admin"
  21.   fmt.Printf("%#v\n", employee) 

打印 Employee 發現 name, age 字段己經賦值了,非常好用。感興趣的可以查看官網,支持非常多的高級玩法

注意:這里是隱式的,有人偏好所有字段顯示賦值,大家怎么看?

 

責任編輯:武曉燕 來源: 董澤潤的技術筆記
相關推薦

2025-03-25 10:49:13

2019-12-11 09:23:51

JavaScriptHTMLXML

2017-04-13 10:08:30

軟件開發開發

2011-09-20 10:56:35

云計算PaaS

2022-04-29 09:00:00

Platform架構內核線程

2018-09-10 09:26:33

2022-08-10 09:03:35

TypeScript前端

2023-01-20 11:51:40

性能測試系統

2018-05-30 15:15:47

混合云公共云私有云

2020-03-03 14:35:34

LinuxRedis命令

2009-06-30 13:00:30

JSP入門

2024-06-04 16:51:11

2023-08-16 15:57:53

2019-10-23 10:36:46

DevSecOpsDevOps

2017-11-14 13:48:26

數據結構學習

2020-03-27 12:30:39

python開發代碼

2016-09-08 14:40:44

2021-01-11 18:33:07

云原生

2014-07-31 17:13:50

編碼程序員

2020-11-23 11:30:00

IDEA技巧開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产网站在线免费观看 | 精品国产乱码久久久久久牛牛 | 日韩久久精品电影 | 97av视频在线观看 | 免费观看一级特黄欧美大片 | 欧美久久一区 | 天天色图 | 久久999 | 狠狠综合久久av一区二区小说 | 国产精品综合色区在线观看 | 亚洲精品日韩视频 | 精品综合在线 | 日本不卡一区 | 男女羞羞视频在线观看 | 久久精品网 | 黑人精品xxx一区一二区 | 国产精品嫩草影院精东 | 中文字幕成人在线 | 91精品一区 | 亚洲欧美综合 | 伊人色综合久久久天天蜜桃 | 狠狠操狠狠干 | 观看av | 精品国产乱码一区二区三 | 亚洲精品一区中文字幕乱码 | 99成人在线视频 | 亚洲成人av在线播放 | 一区二区三区四区电影 | 国产成人免费网站 | 午夜精品久久久久久久久久久久久 | 欧美精品一区二区三区四区 | 久久亚洲春色中文字幕久久久 | 久久久久免费精品国产小说色大师 | 亚洲欧美精品在线观看 | 视频一区二区在线观看 | 成人黄色网址大全 | 人人操日日干 | 国产综合网站 | 91精品国产欧美一区二区 | 成人羞羞国产免费视频 | 色综合天天天天做夜夜夜夜做 |