自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么我們需要在 Go 中使用 Iota

開發(fā) 后端
Go 語言實(shí)際上沒有直接支持枚舉的關(guān)鍵字。一般我們都是通過 const + iota 實(shí)現(xiàn)枚舉的能力。

[[395811]]

本文轉(zhuǎn)載自微信公眾號「吳親強(qiáng)的深夜食堂」,作者吳親庫里。轉(zhuǎn)載本文請聯(lián)系吳親強(qiáng)的深夜食堂公眾號。  

介紹

Go 語言實(shí)際上沒有直接支持枚舉的關(guān)鍵字。一般我們都是通過 const + iota 實(shí)現(xiàn)枚舉的能力。

有人要問了,為什么一定要使用枚舉呢?stackoverflow[1] 上有一個(gè)高贊的回答,如下:

You should always use enums when a variable (especially a method parameter) can only take one out of a small set of possible values. Examples would be things like type constants (contract status: "permanent", "temp", "apprentice"), or flags ("execute now", "defer execution").

If you use enums instead of integers (or String codes), you increase compile-time checking and avoid errors from passing in invalid constants, and you document which values are legal to use.

簡單翻譯一下, 兩點(diǎn)很重要。

  • 當(dāng)一個(gè)變量(尤其是方法參數(shù)) 只能從一小部分可能的值中取出一個(gè)時(shí),理應(yīng)使用枚舉。例如類型常量(合同狀態(tài):永久、臨時(shí)工、學(xué)徒), 或者在做任務(wù)程序時(shí),是立即執(zhí)行還是延遲執(zhí)行的標(biāo)記。
  • 如果使用枚舉而不是整形,則會(huì)增加編譯時(shí)的檢查,避免錯(cuò)誤無效值的傳入,記錄哪些值是合法使用的。

如何實(shí)現(xiàn)枚舉

iota 是 Go 中預(yù)聲明的一個(gè)特殊常量。它會(huì)被預(yù)聲明為0,但是它的值在編譯階段并非是固定的,當(dāng)預(yù)聲明的 iota 出現(xiàn)在一個(gè)常量聲明中,它的值在第n個(gè)常量描述中的值為n(從0開始)。

比如,大家都或多或少了解電商系統(tǒng)。其中的訂單模塊一定會(huì)涉及到訂單狀態(tài)的流轉(zhuǎn)。那么這時(shí)候,我們一般可以這樣定義:

  1. package main 
  2.  
  3. import "fmt" 
  4.  
  5. type OrderStatus int 
  6.  
  7. const ( 
  8.   Cancelled OrderStatus = iota //訂單已取消 0 
  9.   NoPay OrderStatus = iota //未支付 1 
  10.   PendIng OrderStatus = iota // 未發(fā)貨 2 
  11.   Delivered OrderStatus = iota // 已發(fā)貨 3 
  12.   Received OrderStatus = iota // 已收貨 4 
  13.  
  14. func main() { 
  15.   fmt.Println(Cancelled, NoPay) // 打印:0,1 

當(dāng)然,這樣看著好麻煩。其實(shí),其他常量可以重復(fù)上一行 iota 表達(dá)式,我們可以改成這樣。

  1. package main 
  2.  
  3. import "fmt" 
  4.  
  5. type OrderStatus int 
  6.  
  7. const ( 
  8.   Cancelled OrderStatus = iota //訂單已取消 0 
  9.   NoPay //未支付 1 
  10.   PendIng // 未發(fā)貨 2 
  11.   Delivered // 已發(fā)貨 3 
  12.   Received // 已收貨 4 
  13.  
  14. func main() { 
  15.   fmt.Println(Cancelled, NoPay) // 打印:0,1 

有人會(huì)用 0 的值來表示狀態(tài)嗎?一般都不會(huì),我們想以1開頭,那么可以這樣。

  1. package main 
  2.  
  3. import "fmt" 
  4.  
  5. type OrderStatus int 
  6.  
  7. const ( 
  8.   Cancelled OrderStatus = iota+1 //訂單已取消 1 
  9.   NoPay //未支付 2 
  10.   PendIng // 未發(fā)貨 3 
  11.   Delivered // 已發(fā)貨 4 
  12.   Received // 已收貨 5 
  13.  
  14. func main() { 
  15.   fmt.Println(Cancelled, NoPay) // 打印:1,2 

我們還想在 Delivered 后跳過一個(gè)數(shù)字,才是 Received 的值,也就是 Received=6,那么可以借助 _ 符號。

  1. package main 
  2.  
  3. import "fmt" 
  4.  
  5. type OrderStatus int 
  6.  
  7. const ( 
  8.   Cancelled OrderStatus = iota+1 //訂單已取消 1 
  9.   NoPay //未支付 2 
  10.   PendIng // 未發(fā)貨 3 
  11.   Delivered // 已發(fā)貨 4 
  12.   _ 
  13.   Received // 已收貨 6 
  14.  
  15. func main() { 
  16.   fmt.Println(Received) // 打印:6 

順著來可以,倒著當(dāng)然也行。

  1. package main 
  2.  
  3. import "fmt" 
  4.  
  5. type OrderStatus int 
  6.  
  7. const ( 
  8.   Max = 5 
  9.  
  10. const ( 
  11.   Received OrderStatus = Max - iota // 已收貨 5 
  12.   Delivered // 已發(fā)貨 4 
  13.   PendIng // 未發(fā)貨 3 
  14. NoPay //未支付 2 
  15.   Cancelled //訂單已取消 1 
  16.  
  17. func main() { 
  18.   fmt.Println(Received,Delivered) // 打印:5,4 

還可以使用位運(yùn)算,比如在 go 源碼中的包 sync 中的鎖上面有這么一段定義代碼。

  1. const ( 
  2.     mutexLocked = 1 << iota  //1<<0 
  3.     mutexWoken //1<<1 
  4.     mutexStarving //1<<2 
  5.     mutexWaiterShift = iota  //3 
  6.  
  7.  
  8. func main() { 
  9.     fmt.Println("mutexLocked的值",mutexLocked) //打?。? 
  10.     fmt.Println("mutexWoken的值",mutexWoken) //打?。? 
  11.     fmt.Println("mutexStarving的值",mutexStarving) //打?。? 
  12.     fmt.Println("mutexWaiterShift的值",mutexWaiterShift) // 打?。? 

也許有人平常是直接定義常量值或者用字符串來表示的。

比如,上面這些我完全可以用 string 來表示,我還真見過用字符串來表示訂單狀態(tài)的。

  1. package main 
  2.  
  3. import "fmt" 
  4.  
  5. const ( 
  6.   Cancelled = "cancelled" 
  7.   NoPay = "noPay" 
  8.   PendIng = "pendIng" 
  9.   Delivered = "delivered" 
  10.   Received = "received" 
  11.  
  12. var OrderStatusMsg = map[string]string{ 
  13.   Cancelled: "訂單已取消"
  14.   NoPay: "未付款"
  15.   PendIng: "未發(fā)貨"
  16.   Delivered: "已發(fā)貨"
  17.   Received: "已收貨"
  18.  
  19. func main() { 
  20.   fmt.Println(OrderStatusMsg[Cancelled]) 

或者直接定義整形常量值。

  1. package main 
  2.  
  3. import "fmt" 
  4.  
  5. const ( 
  6.   Cancelled = 1 
  7.   NoPay = 2 
  8.   PendIng = 3 
  9.   Delivered = 4 
  10.   Received = 5 
  11.  
  12. var OrderStatusMsg = map[int]string{ 
  13.   Cancelled: "訂單已取消"
  14.   NoPay: "未付款"
  15.   PendIng: "未發(fā)貨"
  16.   Delivered: "已發(fā)貨"
  17.   Received: "已收貨"
  18.  
  19. func main() { 
  20.   fmt.Println(OrderStatusMsg[Cancelled]) 

其實(shí)上述兩種都可以,但是相比之下使用 iota 更有優(yōu)勢。

  • 能保證一組常量的唯一性,人工定義的不能保證。
  • 可以為一組動(dòng)作分享同一種行為。
  • 避免無效值。
  • 提高代碼閱讀性以及維護(hù)。

延伸

按照上面我們所演示的,最后我們可以這樣操作。

  1. package main 
  2.  
  3. import ( 
  4.   "fmt" 
  5.  
  6. type OrderStatus int 
  7.  
  8. const ( 
  9.   Cancelled OrderStatus = iota + 1 //訂單已取消 1 
  10.   NoPay //未支付 2 
  11.   PendIng // 未發(fā)貨 3 
  12.   Delivered // 已發(fā)貨 4 
  13.   Received // 已收貨 5 
  14.  
  15. //公共行為 賦予類型 String() 函數(shù),方便打印值含義 
  16. func (order OrderStatus) String() string { 
  17.   return [...]string{"cancelled""noPay""pendIng""delivered""received"}[order-1] 
  18.  
  19. //創(chuàng)建公共行為 賦予類型 int 函數(shù) EnumIndex() 
  20. func (order OrderStatus) EnumIndex() int { 
  21.   return int(order
  22.  
  23. func main() { 
  24.   var order OrderStatus = Received 
  25.   fmt.Println(order.String()) // 打印:received 
  26.   fmt.Println(order.EnumIndex()) // 打印:5 

總結(jié)

這篇文章主要介紹了 Golang 中對 iota 的使用介紹,以及我們?yōu)槭裁匆褂盟?/p>

不知道大家平常對于此類場景用的什么招數(shù),歡迎下方留言交流。

附錄

[1]

https://stackoverflow.com/questions/4709175/what-are-enums-and-why-are-they-useful

https://levelup.gitconnected.com/implementing-enums-in-golang-9537c433d6e2

https://medium.com/qvault/how-and-why-to-write-enums-in-go-9c1a25649df0

 

責(zé)任編輯:武曉燕 來源: 吳親強(qiáng)的深夜食堂
相關(guān)推薦

2022-06-02 08:48:39

Go枚舉器Iota

2023-11-30 09:00:00

TypeScript開發(fā)

2023-04-13 11:05:10

5G網(wǎng)絡(luò)無線技術(shù)

2020-04-06 14:45:22

云計(jì)算邊緣計(jì)算網(wǎng)絡(luò)

2022-12-01 14:43:56

物聯(lián)網(wǎng)智慧城市

2018-09-14 18:00:29

無損網(wǎng)絡(luò)

2019-08-05 08:42:37

物聯(lián)網(wǎng)IOT技術(shù)

2022-08-26 08:00:19

企業(yè)架構(gòu)IT

2023-09-05 09:49:03

2016-09-27 21:25:08

Go語言Ken Thompso

2012-08-13 09:15:54

Go開發(fā)語言編程語言

2016-01-20 09:54:51

微服務(wù)架構(gòu)設(shè)計(jì)SOA

2015-08-03 10:40:45

動(dòng)效設(shè)計(jì)優(yōu)勢

2015-11-11 13:35:15

2021-05-24 11:30:49

智能建筑IOT物聯(lián)網(wǎng)

2022-01-03 08:06:15

函數(shù)Go數(shù)據(jù)

2021-04-09 09:55:55

DockerGoLinux

2022-07-21 08:00:00

人工智能開發(fā)機(jī)器學(xué)習(xí)

2011-06-08 10:30:08

MongoDB

2018-05-30 14:49:51

編程語言API語法
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號