Enums 类型化常量声明列表

Enums 类型化常量声明列表,enums,constants,go,iota,Enums,Constants,Go,Iota,我希望创建一个具有以下属性的类似枚举的常量列表: 每个标识符的值都是连续的,有一些间隙。我相信IOTA和空白标识符在这方面有帮助。 标识符是模块专用的。 这些常量只能与相同类型的其他常量进行比较。 枚举基于来自的。下面是一些我试图实现的代码,也是非常错误的代码: const Opcode ( _ = iota // skip 0 lookupOp forgetOp getattrOp setattrOp readlinkOp symlink

我希望创建一个具有以下属性的类似枚举的常量列表:

每个标识符的值都是连续的,有一些间隙。我相信IOTA和空白标识符在这方面有帮助。 标识符是模块专用的。 这些常量只能与相同类型的其他常量进行比较。 枚举基于来自的。下面是一些我试图实现的代码,也是非常错误的代码:

const Opcode (
    _ = iota // skip 0
    lookupOp
    forgetOp
    getattrOp
    setattrOp
    readlinkOp
    symlinkOp // 6
    _ // skip 7
    mknodOp // 8
    // et cetera ad nauseam
)

这是保险丝操作码的密码。它是从。通常,您会编写一个脚本来实现这一点;我用了一个文本编辑器。由于常量值与C枚举值匹配,因此使用显式值

package fuse

type opCode int32

const (
    opLookup      = 1
    opForget      = 2
    opGetattr     = 3
    opSetattr     = 4
    opReadlink    = 5
    opSymlink     = 6
    opMknod       = 8
    opMkdir       = 9
    opUnlink      = 10
    opRmdir       = 11
    opRename      = 12
    opLink        = 13
    opOpen        = 14
    opRead        = 15
    opWrite       = 16
    opStatfs      = 17
    opRelease     = 18
    opFsync       = 20
    opSetxattr    = 21
    opGetxattr    = 22
    opListxattr   = 23
    opRemovexattr = 24
    opFlush       = 25
    opInit        = 26
    opOpendir     = 27
    opReaddir     = 28
    opReleasedir  = 29
    opFsyncdir    = 30
    opGetlk       = 31
    opSetlk       = 32
    opSetlkw      = 33
    opAccess      = 34
    opCreate      = 35
    opInterrupt   = 36
    opBmap        = 37
    opDestroy     = 38
    opIoctl       = 39
    opPoll        = 40
    opNotifyReply = 41
)

这是保险丝操作码的密码。它是从。通常,您会编写一个脚本来实现这一点;我用了一个文本编辑器。由于常量值与C枚举值匹配,因此使用显式值

package fuse

type opCode int32

const (
    opLookup      = 1
    opForget      = 2
    opGetattr     = 3
    opSetattr     = 4
    opReadlink    = 5
    opSymlink     = 6
    opMknod       = 8
    opMkdir       = 9
    opUnlink      = 10
    opRmdir       = 11
    opRename      = 12
    opLink        = 13
    opOpen        = 14
    opRead        = 15
    opWrite       = 16
    opStatfs      = 17
    opRelease     = 18
    opFsync       = 20
    opSetxattr    = 21
    opGetxattr    = 22
    opListxattr   = 23
    opRemovexattr = 24
    opFlush       = 25
    opInit        = 26
    opOpendir     = 27
    opReaddir     = 28
    opReleasedir  = 29
    opFsyncdir    = 30
    opGetlk       = 31
    opSetlk       = 32
    opSetlkw      = 33
    opAccess      = 34
    opCreate      = 35
    opInterrupt   = 36
    opBmap        = 37
    opDestroy     = 38
    opIoctl       = 39
    opPoll        = 40
    opNotifyReply = 41
)

你想要这样的东西。您仍然可以将这些常量与文字整数进行比较。没有办法防止这种情况发生,但是任何与其他整数值的比较或赋值都会导致编译器错误

type opCode int

const (
    lookupOp opCode = iota+1
    forgetOp
    getattrOp
    setattrOp
    readlinkOp
    symlinkOp // 6
    _         // skip 7
    mknodOp   // 8
    // et cetera ad nauseam
)

如果你真的想防止外部包看到这些是整数常量的事实,但是你仍然希望它是可比的,那么你可以考虑这样做,

type OpCode struct {
    code opCode
}

并且只在API中公开操作码。我还建议明确记录它的可比性。

您想要这样的东西。您仍然可以将这些常量与文字整数进行比较。没有办法防止这种情况发生,但是任何与其他整数值的比较或赋值都会导致编译器错误

type opCode int

const (
    lookupOp opCode = iota+1
    forgetOp
    getattrOp
    setattrOp
    readlinkOp
    symlinkOp // 6
    _         // skip 7
    mknodOp   // 8
    // et cetera ad nauseam
)

如果你真的想防止外部包看到这些是整数常量的事实,但是你仍然希望它是可比的,那么你可以考虑这样做,

type OpCode struct {
    code opCode
}

并且只在API中公开操作码。我还建议明确记录它的可比性。

@Jessta:额外的间接层在编译器afaict中没有强制执行任何内容。为什么不使用iota?为什么是int32?@Ross Light:我在链接端点观察到了什么?我尝试了间接建议,但没有奏效。我猜这就是为什么@Jessta将其从他的答案中删除的原因。我认为这是因为他提出的解决方案仍然可以转换为int32。我留下的链接是为了说明编译器然后强制这些常量是操作码类型的-如果没有强制转换,它们无法与int32s进行比较。我只是不明白为什么需要强制执行操作码不能与任何其他类型进行比较。Go的类型系统旨在防止您犯明显的错误,但它仍然具有Python的成人心态。只需将操作码设为int。使用==进行比较。它使事情变得更简单。@RossLight为什么编译器要强制执行任何东西?让我们都用汇编语言编程。夸张,我知道,但我真的不明白为什么人们认为语言应该防止一些人为错误,而不是其他错误…@Jessta:额外的间接层在编译器afaict中没有强制执行任何内容。你为什么不使用iota?为什么是int32?@Ross Light:我在链接端点观察到了什么?我尝试了间接建议,但没有奏效。我猜这就是为什么@Jessta将其从他的答案中删除的原因。我认为这是因为他提出的解决方案仍然可以转换为int32。我留下的链接是为了说明编译器然后强制这些常量是操作码类型的-如果没有强制转换,它们无法与int32s进行比较。我只是不明白为什么需要强制执行操作码不能与任何其他类型进行比较。Go的类型系统旨在防止您犯明显的错误,但它仍然具有Python的成人心态。只需将操作码设为int。使用==进行比较。它使事情变得更简单。@RossLight为什么编译器要强制执行任何东西?让我们都用汇编语言编程。夸张,我知道,但我真的不明白为什么人们认为语言应该防止一些人为错误,而不是其他错误…使操作码成为一个结构意味着你不能从上面使用const技巧,或者很容易地使用switch语句,等+1将操作码保持为整数。让一个数字成为一个数字。@RossLight数字通常具有不同的语义,让系统防止您将它们混淆通常是有帮助的。例如,添加DegreesC和bananaid没有多大意义,没有必要使用Eq方法。只要它们的字段具有可比性,就可以使用op1==op2.Yes替换op1.Eqop2。不过,我在写答案时没有这样做!将相应地进行编辑。将操作码设置为结构意味着您不能使用上面的const技巧,或轻松使用switch语句等+1将操作码保持为int。将数字设为数字。@RossLight数字通常具有不同的语义含义,让系统防止您将它们合并通常很有帮助。增加学位没有多大意义
例如,C和BananaIDs。不需要Eq方法。只要它们的字段具有可比性,就可以使用op1==op2.Yes替换op1.Eqop2。不过,我在写答案时没有这样做!将进行相应的编辑。请说明为什么显式值最适合向上投票。在尝试了所有给定的选项之后,这个方法看起来最干净、最简单。为什么要创建一个操作码类型?Go怎么知道opLookup是一个值为1的操作码而不是一个普通的int呢?我同意@weberc2;您不需要声明const块中的标识符是opCode类型吗?否则,您必须在任何时候将变量初始化为这些常量之一时显式声明类型,这样您就失去了其他类型功能,如操作码上的方法。@MattJoiner wrt为什么显式值最适合某些情况,例如,常量值与C enum值匹配,在这种情况下,代码可能应该像syscall包中一样通过go generate生成。即使值为0、1、2或其他任何值,如果iota很容易实现,那么最好是明确的,如果您遵循指定明确值的规范/任何内容,例如seek set/current/end。iota最适用于价值本身并不重要的情况。请说明为什么明确的价值最适用于向上投票。在尝试了所有给定的选项之后,这个方法看起来最干净、最简单。为什么要创建一个操作码类型?Go怎么知道opLookup是一个值为1的操作码而不是一个普通的int呢?我同意@weberc2;您不需要声明const块中的标识符是opCode类型吗?否则,您必须在任何时候将变量初始化为这些常量之一时显式声明类型,这样您就失去了其他类型功能,如操作码上的方法。@MattJoiner wrt为什么显式值最适合某些情况,例如,常量值与C enum值匹配,在这种情况下,代码可能应该像syscall包中一样通过go generate生成。即使值为0、1、2或其他任何值,如果iota很容易实现,那么最好是明确的,如果您遵循指定明确值的规范/任何内容,例如seek set/current/end。物联网最适合价值本身并不重要的情况。