关于golang:iota-在-Go-中的使用

52次阅读

共计 3760 个字符,预计需要花费 10 分钟才能阅读完成。

文章继续更新,微信搜一搜「吴亲强的深夜食堂

介绍

Go 语言实际上没有间接反对枚举的关键字。个别咱们都是通过 const + iota 实现枚举的能力。

有人要问了,为什么肯定要应用枚举呢?stackoverflow 上有一个高赞的答复,如下:

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.

简略翻译一下,两点很重要。

  • 当一个变量 (尤其是办法参数) 只能从一小部分可能的值中取出一个时,理当应用枚举。
    例如类型常量(合同状态:永恒、临时工、学徒),或者在做工作程序时,是立刻执行还是提早执行的标记。
  • 如果应用枚举而不是整形,则会减少编译时的查看,防止谬误有效值的传入,记录哪些值是非法应用的。

如何实现枚举

iota 是 Go 中预申明的一个非凡常量。它会被预申明为 0,然而它的值在编译阶段并非是固定的,当预申明的 iota 呈现在一个常量申明中的时候,它的值在第 n 个常量形容中的值为 n(从 0 开始)。所以它只在同类型多个常量申明的状况下才显得有意义。

比方,大家都理解的电商,订单零碎肯定会波及到订单状态的流转。那么这时候,咱们个别能够这样做:

package main

import "fmt"

type OrderStatus int

const (Cancelled OrderStatus = iota // 订单已勾销 0  NoPay OrderStatus = iota // 未领取  1  PendIng OrderStatus = iota // 未发货 2  Delivered OrderStatus = iota // 已发货 3  Received OrderStatus = iota // 已收货 4)

func main() {fmt.Println(Cancelled, NoPay) // 打印:0,1
}

当然,这样看着好麻烦。其实,其余常量能够反复上一行 iota 表达式,咱们能够改成这样。

package main

import "fmt"

type OrderStatus int

const (Cancelled OrderStatus = iota // 订单已勾销 0  NoPay // 未领取 1  PendIng // 未发货 2  Delivered // 已发货 3  Received // 已收货 4)

func main() {fmt.Println(Cancelled, NoPay) // 打印:0,1
}

有人会用 0 的值来示意状态吗?个别都不会,咱们想以 1 结尾,那么能够这样。

package main

import "fmt"

type OrderStatus int

const (
  Cancelled OrderStatus = iota+1 // 订单已勾销 1
  NoPay // 未领取 2  PendIng // 未发货 3  Delivered // 已发货 4  Received // 已收货 5)

func main() {fmt.Println(Cancelled, NoPay) // 打印:1,2
}

咱们还想在 Delivered 后跳过一个数字,才是 Received 的值, 也就是 Received=6,那么能够借助 _ 符号。

package main

import "fmt"

type OrderStatus int

const (
  Cancelled OrderStatus = iota+1 // 订单已勾销 1
  NoPay // 未领取 2  PendIng // 未发货 3  Delivered // 已发货 4  _
 Received // 已收货 6)

func main() {fmt.Println(Received) // 打印:6
}

顺着来能够,倒着当然也行。

package main

import "fmt"

type OrderStatus int

const (Max = 5)

const (Received OrderStatus = Max - iota // 已收货  5  Delivered // 已发货 4  PendIng // 未发货 3  NoPay // 未领取 2  Cancelled // 订单已勾销 1)

func main() {fmt.Println(Received,Delivered) // 打印:5,4
}

你还能够应用位运算,比方在 go 源码中的包 sync 中的锁下面有这么一段代码。

const (mutexLocked = 1 << iota  //1<<0 mutexWoken               //1<<1 mutexStarving            //1<<2 mutexWaiterShift = iota  //3)

func main() {fmt.Println("mutexLocked 的值",mutexLocked) // 打印:1 fmt.Println("mutexWoken 的值",mutexWoken) // 打印:2 fmt.Println("mutexStarving 的值",mutexStarving) // 打印:4 fmt.Println("mutexWaiterShift 的值",mutexWaiterShift) // 打印:3}

可能有人平时是间接定义常量值或者用字符串来示意的。

比方,下面这些我齐全能够用 string 来示意,我还真见过用字符串来示意订单状态的。

package main

import "fmt"

const (Cancelled = "cancelled"  NoPay = "noPay"  PendIng = "pendIng"  Delivered = "delivered"  Received = "received")

var OrderStatusMsg = map[string]string{
  Cancelled: "订单已勾销",
  NoPay:     "未付款",
  PendIng:   "未发货",
  Delivered: "已发货",
  Received:  "已收货",
}

func main() {fmt.Println(OrderStatusMsg[Cancelled])
}

或者间接定义整形常量值。

package main

import "fmt"

const (Cancelled = 1  NoPay = 2  PendIng = 3  Delivered = 4  Received = 5)

var OrderStatusMsg = map[int]string{
  Cancelled: "订单已勾销",
  NoPay:     "未付款",
  PendIng:   "未发货",
  Delivered: "已发货",
  Received:  "已收货",
}

func main() {fmt.Println(OrderStatusMsg[Cancelled])
}

其实上述两种都能够,然而相比之下应用 iota 更有劣势。

  • 能保障一组常量的唯一性,人工定义的不能保障。
  • 能够为一组动作分享同一种行为。
  • 防止有效值。
  • 进步代码浏览性以及保护。

延长

依照下面咱们所演示的,最初咱们能够这样操作。

package main

import ("fmt")

type OrderStatus int

const (Cancelled OrderStatus = iota + 1 // 订单已勾销 1  NoPay // 未领取 2  PendIng // 未发货 3  Delivered // 已发货 4  Received // 已收货 5)

// 公共行为 赋予类型 String() 函数,不便打印值含意
func (order OrderStatus) String() string { return [...]string{"cancelled", "noPay", "pendIng", "delivered", "received"}[order-1]
}

// 创立公共行为 赋予类型 int 函数 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
}

总结

这篇文章次要介绍了 Golang 中对 iota 的应用介绍,以及咱们为什么要应用它。

不晓得大家平时对于此类场景是用的什么招数,欢送下方留言交换。

正文完
 0