Tips

Go 语言枚举值

2022-05-23  本文已影响0人  Sun东辉

首先,我们看一段代码:

const (
    x = iota
    y
    z = "zz"
    k
    p = iota
)

func main() {
    fmt.Println(x, y, z, k, p)   // 0 1 zz zz 4
}

为什么会这样?

首先,我们分析 k 为什么是 “zz”?

const 声明有个重要特点,第一个常量必须指定一个表达式,后续的常量如果没有表达式,则继承上面的表达式。这里 k 的前一个表达式为 “zz”,所以 k 的值为 “zz”。

现在,我们再来看看 p 为什么是 4? 其实,这和 go 语言底层的实现有关,const 块中每一行在 Go 中使用 spec 数据结构描述, spec 声明如下:

ValueSpec struct {
        Doc     *CommentGroup // associated documentation; or nil
        Names   []*Ident      // value names (len(Names) > 0) 保存了一行中定义的常量,如果一行定义 N 个常量,那么 ValueSpec.Names 切片长度即为 N。
        Type    Expr          // value type; or nil
        Values  []Expr        // initial values; or nil
        Comment *CommentGroup // line comments; or nil
}
Ident struct {
        NamePos token.Pos // identifier position
        Name    string    // identifier name
        Obj     *Object   // denoted object; or nil
}

编译期构造常量的伪代码如下:

for index, value := range ValueSpecs {
        for _, ident := range value.Names {
                obj := NewConst(ident.name, index, value...) // 此处将 i 值传入,用于构造常量
                 ...
        }
}

可以看出,iota 的值其实是通过它的索引推导出来的,即 const 声明块中每新增一行 iota 值自增 1,这里初始化的 iota 为 0,p 的索引为 4,`0 + 4 = 4`,所以 p 的值为 4。

上一篇 下一篇

猜你喜欢

热点阅读