Home  >  Article  >  Backend Development  >  How to use iota in Go

How to use iota in Go

藏色散人
藏色散人forward
2021-04-29 11:52:432118browse

The following tutorial column from golang will introduce how to use iota in Go. I hope it will be helpful to friends who need it!

Introduction

The Go language actually does not directly support the enumeration keyword. Generally, we implement enumeration capabilities through const iota.

Someone may ask, why must we use enumerations? There is a highly praised answer on stackoverflow, as follows:

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.

Simple translation, two points Very important.

  • When a variable (especially a method parameter) can only take one of a small number of possible values, an enumeration should be used.
    For example, type constants (contract status: permanent, temporary worker, apprentice), or a flag for immediate or delayed execution when doing a task program.
  • If you use enumerations instead of integers, compile-time checks will be added to avoid incorrect invalid values ​​being passed in and record which values ​​are legally used.

How to implement enumerations

iota is a special constant pre-declared in Go. It will be predeclared as 0, but its value is not fixed at the compilation stage. When the predeclared iota appears in a constant declaration, its value is in the nth constant description. The value of is n (starting from 0). So it only makes sense if there are multiple constant declarations of the same type.

For example, as everyone knows about e-commerce, the order system will definitely involve the flow of order status. So at this time, we can generally do this:

package mainimport "fmt"type OrderStatus intconst (
  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}

Of course, this looks very troublesome. In fact, other constants can repeat the iota expression in the previous line, and we can change it to this.

package mainimport "fmt"type OrderStatus intconst (
  Cancelled OrderStatus = iota //订单已取消 0  NoPay //未支付 1  PendIng // 未发货 2  Delivered // 已发货 3  Received // 已收货 4)func main() {
  fmt.Println(Cancelled, NoPay) // 打印:0,1}

Does anyone use a value of 0 to represent status? Generally not, we want to start with 1, so that's fine.

package mainimport "fmt"type OrderStatus intconst (
  Cancelled OrderStatus = iota+1 //订单已取消 1
  NoPay //未支付 2  PendIng // 未发货 3  Delivered // 已发货 4  Received // 已收货 5)func main() {
  fmt.Println(Cancelled, NoPay) // 打印:1,2}

We also want to skip a number after Delivered, which is the value of Received, that is, Received=6, then yes Use the _ symbol.

package mainimport "fmt"type OrderStatus intconst (
  Cancelled OrderStatus = iota+1 //订单已取消 1
  NoPay //未支付 2  PendIng // 未发货 3  Delivered // 已发货 4  _
 Received // 已收货 6)func main() {
  fmt.Println(Received) // 打印:6}

You can do it along the way, and of course backwards.

package mainimport "fmt"type OrderStatus intconst (
  Max = 5)const (
  Received OrderStatus = Max - iota // 已收货  5  Delivered // 已发货 4  PendIng // 未发货 3  NoPay //未支付 2  Cancelled //订单已取消 1)func main() {
  fmt.Println(Received,Delivered) // 打印:5,4}

You can also use bit operations, for example, there is such a piece of code on the lock in the package sync in the go source code.

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}

Maybe some people usually define constant values ​​directly or use strings to represent them.

For example, I can use string to represent the above. I have actually seen strings used to represent order status.

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])
}

Or directly define the integer constant value.

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])
}

In fact, both of the above are possible, but using iota has more advantages.

  • can guarantee the uniqueness of a set of constants, but artificial definition cannot.
  • You can share the same behavior for a group of actions.
  • Avoid invalid values.
  • Improve code readability and maintenance.

Extension

According to what we demonstrated above, we can finally do this.

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
}

Summary

This article mainly introduces the use of iota in Golang and why we should use it.

I don’t know what tricks you usually use for this kind of scene, please leave a message below to exchange.                                                                                                                    

The above is the detailed content of How to use iota in Go. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:learnku.com. If there is any infringement, please contact admin@php.cn delete