在 Golang 中使用 Iota——使用 Iota 声明增量常量值

文章目录

Go 的 iota 怎么用?在这篇文章中,我们将了解 Go 中的“iota”标识符、它的使用方式以及何时不使用它。

“iota”标识符用于表示 Go 中基于整数的常量,是声明常量序列的便捷方式,同时保持代码可读性。

使用 Iota 进行常量声明

通常,常量可以通过指定其值来声明,例如:

const (
	SPADES   = 1
	HEARTS   = 2
	DIAMONDS = 3
	CLUBS    = 4
)

func main() {
	fmt.Println("SPADES:", SPADES, "HEARTS:", HEARTS, "DIAMONDS:", DIAMONDS, "CLUBS:", CLUBS)
}

输出:

SPADES: 1 HEARTS: 2 DIAMONDS: 3 CLUBS: 4

然而,我们可以使用 iota 并避免显式声明增量整数值:

const (
	SPADES   = iota
	HEARTS   = iota
	DIAMONDS = iota
	CLUBS    = iota
)

func main() {
	fmt.Println("SPADES:", SPADES, "HEARTS:", HEARTS, "DIAMONDS:", DIAMONDS, "CLUBS:", CLUBS)
}

输出:

SPADES: 0 HEARTS: 1 DIAMONDS: 2 CLUBS: 3

从这个例子中,我们可以观察到 iota 的两个属性:

  1. iota 的值随着每个常量声明而递增
  2. 它从 0 开始

我们也可以在第一个 iota 之后省略后面的 iota 声明,所以这段代码会给出相同的结果:

const (
	SPADES = iota
	HEARTS
	DIAMONDS
	CLUBS
)

从非零索引开始

正如我们在前面的示例中看到的,iota0 开始,但我们可以通过将给定数量添加到第一个声明来更改基值。

因此,如果我们想要与第一个示例相同的结果,其中 SPADES = 1,那么我们可以如下声明常量:

const (
    // 现在,索引从 1 开始
	SPADES = iota + 1
	HEARTS
	DIAMONDS
	CLUBS
)

输出:

SPADES: 1 HEARTS: 2 DIAMONDS: 3 CLUBS: 4

一般来说,如果我们想从索引 n 开始,我们可以用 iota + <n> 开始常量声明

跳过值

请记住,每个常量声明的 iota 值都会递增。所以,如果我们想跳过一个值,我们可以声明一个空常量值:

const (
	SPADES = iota
	HEARTS
	_ // iota 的值会增加,因为这仍然是一个常量声明
	DIAMONDS
	CLUBS
)

输出:

SPADES: 0 HEARTS: 1 DIAMONDS: 3 CLUBS: 4

你可以添加任意数量的空常量声明,以跳过前面的多个值。

自定义数学运算

虽然 iota 的值是递增的,但我们可以利用基本的数学运算来修改分配给每个常量的最终值。

例如,如果我们使用 iota * 10,它将为每个 const 声明给出 10 的第 n 个倍数:

const (
	ZERO = 10 * iota // = 10 * 0
	TEN // = 10 * 1
	TWENTY // = 10 * 2
	THIRTY // = 10 * 3
)

func main() {
	fmt.Println("ZERO:", ZERO, "TEN:", TEN, "TWENTY:", TWENTY, "THIRTY:", THIRTY)
}

输出:

ZERO: 0 TEN: 10 TWENTY: 20 THIRTY: 30

类似地,我们可以使用左移操作来进行指数递增:

const (
	BYTE     = 1 << (iota * 10) // = 1 << 0
	KILOBYTE                    // = 1 << 10
	MEGABYTE                    // = 1 << 20
	GIGABYTE                    // = 1 << 30
)

func main() {
	fmt.Println("BYTE:", BYTE, "KILOBYTE:", KILOBYTE, "MEGABYTE:", MEGABYTE, "GIGABYTE:", GIGABYTE)
}

输出:

BYTE: 1 KILOBYTE: 1024 MEGABYTE: 1048576 GIGABYTE: 1073741824

根据官方文档定义,在同一个 ConstSpec 中多次使用 iota 都具有相同的值:

ConstSpec      = IdentifierList [ [ Type ] "=" ExpressionList ] .
const (
	bit0, mask0 = 1 << iota, 1<<iota - 1  // bit0 == 1, mask0 == 0  (iota == 0)
	bit1, mask1                           // bit1 == 2, mask1 == 1  (iota == 1)
	_, _                                  //                        (iota == 2, unused)
	bit3, mask3                           // bit3 == 8, mask3 == 7  (iota == 3)
)

重置 Iota 值

iota 值仅在常量声明块内递增。因此,一旦我们在不同的声明块中声明了另一组常量,iota 值就会重置。

例如,我们可以在同一文件中声明前面示例中讨论的所有常量:

const (
	SPADES = iota
	HEARTS
	DIAMONDS
	CLUBS
)

// iota 在这里重置
const (
	ZERO = 10 * iota
	TEN
	TWENTY
	THIRTY
)

// iota 在这里重置
const (
	BYTE     = 1 << (iota * 10) // = 1 << 0
	KILOBYTE                    // = 1 << 10
	MEGABYTE                    // = 1 << 20
	GIGABYTE                    // = 1 << 30
)

func main() {
	fmt.Println("SPADES:", SPADES, "HEARTS:", HEARTS, "DIAMONDS:", DIAMONDS, "CLUBS:", CLUBS)
	fmt.Println("ZERO:", ZERO, "TEN:", TEN, "TWENTY:", TWENTY, "THIRTY:", THIRTY)
	fmt.Println("BYTE:", BYTE, "KILOBYTE:", KILOBYTE, "MEGABYTE:", MEGABYTE, "GIGABYTE:", GIGABYTE)
}

输出:

SPADES: 0 HEARTS: 1 DIAMONDS: 3 CLUBS: 4
ZERO: 0 TEN: 10 TWENTY: 20 THIRTY: 30
BYTE: 1 KILOBYTE: 1024 MEGABYTE: 1048576 GIGABYTE: 1073741824

为什么 Iota 是有用的

使用 iota 是声明任意常量或枚举的一种更具可读性和惯用的方式。

使用 iota,我们可以添加更多常量值,而无需考虑要分配的下一个数值。

它还可以帮助我们避免代码中出现某些类型的错误。

为了说明这一点,假设我们有一大堆错误码要声明为常量。在这些情况下,很容易犯两次分配相同值的人为错误:

const (
	ERR_ABC = 1
	ERR_DEF = 2
	ERR_HIJ = 3
	ERR_KLM = 3  // 我丢
	ERR_NOP = 4
	ERR_QRS = 5
)

如果我们使用 iota 来分配这些值,我们就不会遇到这个问题,我们的代码也不容易出错。

什么时候应该避免使用 Iota

当有任意值或增量值用作常量时,最好使用 Iota。

在某些情况下,常量之间没有任何顺序关系。例如,秒、分、小时和天等时间单位可以表示为非顺序常量:

const (
	SECOND = 1
	MINUTE = 60 * SECOND
	HOUR   = 60 * MINUTE
	DAY    = 24 * HOUR
)

在这种情况下,我们无法使用 iota,因为连续常量之间的关系不是增加相同的数量。

我们不应该使用 iota 的另一种情况是数值不是任意的。例如,表示一副牌中的牌总数,或王牌总数:

const (
  TOTAL_CARDS = 52
  TOTAL_JOKERS = 2
)

在这种情况下,常量的值是有意义的,而不是顺序的,所以最好不要使用 iota

结语

不知你是否好奇过这个 iota 标识符到底是啥意思(不是用法),你也许会认为它是一个短语或单词的缩写,然而 “iota” 并不是某物的首字母缩写词,它本身就是一个词,源自古希腊语 ἰῶτα (iôta)。

“iota” 表示希腊字母表中最小的字母,与 0 是枚举类型的最小值的含义相同,在英语中,它是一个具有反映希腊字母定义的词,类似于 “A” 读作 “alpha”。

iota 的词典定义:https://www.vocabulary.com/dictionary/iota

  • 美式发音:/aɪˈoʊdə/
  • 英式发音:/aɪˈəʊtə/

也可以看看


全国大流量卡免费领

19元月租ㆍ超值优惠ㆍ长期套餐ㆍ免费包邮ㆍ官方正品