這篇文章將為大家詳細(xì)講解有關(guān)iota在Go中的使用方法,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
成都創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供曹妃甸網(wǎng)站建設(shè)、曹妃甸做網(wǎng)站、曹妃甸網(wǎng)站設(shè)計(jì)、曹妃甸網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、曹妃甸企業(yè)網(wǎng)站模板建站服務(wù),10余年曹妃甸做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
golang是一種編譯語(yǔ)言,可以將代碼編譯為機(jī)器代碼,編譯后的二進(jìn)制文件可以直接部署到目標(biāo)機(jī)器而無(wú)需額外的依賴,所以golang的性能優(yōu)于其他的解釋性語(yǔ)言,且可以在golang中使用goroutine來(lái)實(shí)現(xiàn)并發(fā)性,它提供了一個(gè)非常優(yōu)雅的goroutine調(diào)度程序系統(tǒng),可以很容易地生成數(shù)百萬(wàn)個(gè)goroutine。
Go 語(yǔ)言實(shí)際上沒有直接支持枚舉的關(guān)鍵字。一般我們都是通過 const
+ iota
實(shí)現(xiàn)枚舉的能力。
有人要問了,為什么一定要使用枚舉呢?stackoverflow
上有一個(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.BTW, overuse of enums might mean that your methods do too much (it’s often better to have several separate methods, rather than one method that takes several flags which modify what it does), but if you have to use flags or type codes, enums are the way to go.
簡(jiǎn)單翻譯一下, 兩點(diǎn)很重要。
當(dāng)一個(gè)變量(尤其是方法參數(shù)) 只能從一小部分可能的值中取出一個(gè)時(shí),理應(yīng)使用枚舉。
例如類型常量(合同狀態(tài):永久、臨時(shí)工、學(xué)徒), 或者在做任務(wù)程序時(shí),是立即執(zhí)行還是延遲執(zhí)行的標(biāo)記。
如果使用枚舉而不是整形,則會(huì)增加編譯時(shí)的檢查,避免錯(cuò)誤無(wú)效值的傳入,記錄哪些值是合法使用的。
iota
是 Go 中預(yù)聲明的一個(gè)特殊常量。它會(huì)被預(yù)聲明為0,但是它的值在編譯階段并非是固定的,當(dāng)預(yù)聲明的 iota
出現(xiàn)在一個(gè)常量聲明中的時(shí)候,它的值在第n個(gè)常量描述中的值為n(從0開始)。所以它只在同類型多個(gè)常量聲明的情況下才顯得有意義。
比如,大家都了解的電商,訂單系統(tǒng)一定會(huì)涉及到訂單狀態(tài)的流轉(zhuǎn)。那么這時(shí)候,我們一般可以這樣做:
package mainimport "fmt"type OrderStatus intconst ( Cancelled OrderStatus = iota //訂單已取消 0 NoPay OrderStatus = iota //未支付 1 PendIng OrderStatus = iota // 未發(fā)貨 2 Delivered OrderStatus = iota // 已發(fā)貨 3 Received OrderStatus = iota // 已收貨 4)func main() { fmt.Println(Cancelled, NoPay) // 打印:0,1}
當(dāng)然,這樣看著好麻煩。其實(shí),其他常量可以重復(fù)上一行 iota
表達(dá)式,我們可以改成這樣。
package mainimport "fmt"type OrderStatus intconst ( Cancelled OrderStatus = iota //訂單已取消 0 NoPay //未支付 1 PendIng // 未發(fā)貨 2 Delivered // 已發(fā)貨 3 Received // 已收貨 4)func main() { fmt.Println(Cancelled, NoPay) // 打印:0,1}
有人會(huì)用 0 的值來(lái)表示狀態(tài)嗎?一般都不會(huì),我們想以1開頭,那么可以這樣。
package mainimport "fmt"type OrderStatus intconst ( Cancelled OrderStatus = iota+1 //訂單已取消 1 NoPay //未支付 2 PendIng // 未發(fā)貨 3 Delivered // 已發(fā)貨 4 Received // 已收貨 5)func main() { fmt.Println(Cancelled, NoPay) // 打印:1,2}
我們還想在 Delivered
后跳過一個(gè)數(shù)字,才是 Received
的值,也就是 Received=6
,那么可以借助 _
符號(hào)。
package mainimport "fmt"type OrderStatus intconst ( Cancelled OrderStatus = iota+1 //訂單已取消 1 NoPay //未支付 2 PendIng // 未發(fā)貨 3 Delivered // 已發(fā)貨 4 _ Received // 已收貨 6)func main() { fmt.Println(Received) // 打印:6}
順著來(lái)可以,倒著當(dāng)然也行。
package mainimport "fmt"type OrderStatus intconst ( Max = 5)const ( Received OrderStatus = Max - iota // 已收貨 5 Delivered // 已發(fā)貨 4 PendIng // 未發(fā)貨 3 NoPay //未支付 2 Cancelled //訂單已取消 1)func main() { fmt.Println(Received,Delivered) // 打印:5,4}
你還可以使用位運(yùn)算,比如在 go 源碼中的包 sync
中的鎖上面有這么一段代碼。
const ( mutexLocked = 1 << iota //1<<0 mutexWoken //1<<1 mutexStarving //1<<2 mutexWaiterShift = iota //3)func main() { fmt.Println("mutexLocked的值",mutexLocked) //打?。? fmt.Println("mutexWoken的值",mutexWoken) //打印:2 fmt.Println("mutexStarving的值",mutexStarving) //打?。? fmt.Println("mutexWaiterShift的值",mutexWaiterShift) // 打?。?}
可能有人平常是直接定義常量值或者用字符串來(lái)表示的。
比如,上面這些我完全可以用 string
來(lái)表示,我還真見過用字符串來(lái)表示訂單狀態(tài)的。
package mainimport "fmt"const ( Cancelled = "cancelled" NoPay = "noPay" PendIng = "pendIng" Delivered = "delivered" Received = "received")var OrderStatusMsg = map[string]string{ Cancelled: "訂單已取消", NoPay: "未付款", PendIng: "未發(fā)貨", Delivered: "已發(fā)貨", Received: "已收貨",}func main() { fmt.Println(OrderStatusMsg[Cancelled])}
或者直接定義整形常量值。
package mainimport "fmt"const ( Cancelled = 1 NoPay = 2 PendIng = 3 Delivered = 4 Received = 5)var OrderStatusMsg = map[int]string{ Cancelled: "訂單已取消", NoPay: "未付款", PendIng: "未發(fā)貨", Delivered: "已發(fā)貨", Received: "已收貨",}func main() { fmt.Println(OrderStatusMsg[Cancelled])}
其實(shí)上述兩種都可以,但是相比之下使用 iota
更有優(yōu)勢(shì)。
能保證一組常量的唯一性,人工定義的不能保證。
可以為一組動(dòng)作分享同一種行為。
避免無(wú)效值。
提高代碼閱讀性以及維護(hù)。
按照上面我們所演示的,最后我們可以這樣操作。
package mainimport ( "fmt")type OrderStatus intconst ( Cancelled OrderStatus = iota + 1 //訂單已取消 1 NoPay //未支付 2 PendIng // 未發(fā)貨 3 Delivered // 已發(fā)貨 4 Received // 已收貨 5)//公共行為 賦予類型 String() 函數(shù),方便打印值含義func (order OrderStatus) String() string { return [...]string{"cancelled", "noPay", "pendIng", "delivered", "received"}[order-1]}//創(chuàng)建公共行為 賦予類型 int 函數(shù) EnumIndex()func (order OrderStatus) EnumIndex() int { return int(order)}func main() { var order OrderStatus = Received fmt.Println(order.String()) // 打印:received fmt.Println(order.EnumIndex()) // 打印:5}
關(guān)于“iota在Go中的使用方法”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。