Golang中如何定义带预定义选项列表的变量
Golang中如何定义带预定义选项列表的变量 大家好,我想创建一个变量,它只能取三个值中的一个:1、3 或两者。我正在寻找在 Go 中实现这一功能的方法。是否有 Go 特有的方式来实现这个?谢谢!
具有讽刺意味的是,您链接的维基百科页面中列出了Go语言:
Go 使用
iota关键字来创建枚举常量
更多关于Golang中如何定义带预定义选项列表的变量的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这确实具有讽刺意味。
在计算机编程中,枚举类型(在R编程语言中也称为枚举、enum或因子,在统计学中称为分类变量)是一种数据类型,由一组称为该类型的元素、成员、枚举项或枚举器的命名值组成。
一种数据类型,由一组称为该类型的元素、成员、枚举项或枚举器的命名值组成。
Go语言并没有这种特性。他们将Go语言列入其中是自相矛盾的。
大家好,非常感谢各位详尽的回复。这些回复提供了广泛的学习思路和构建基础。
我的场景是这样的:卖家将通过其用户界面设置许可证购买的期限选项。然后,买家只会看到这些选项。例如,如果卖家同时启用了两个选项,那么买家可以选择购买1年期或3年期的许可证。如果卖家只选择了一个选项,那么买家就只能购买该期限的许可证。我将仔细研究并理解你们提供的所有实现方案。
非常感谢。
能否提供更多关于您使用场景的信息?如果您确实需要一个只能处于这三种状态之一的变量,可以这样做:https://play.golang.org/p/vowJmrzr1Ml,但我个人认为这段代码有些笨拙。如果您需要处理(反)序列化,它会变得更加笨拙。我可能会在某个地方(Web服务?UI字段的验证器?这取决于上下文)添加一些验证逻辑来处理值的检查,以确保它是三个选项之一,而不是将其构建到类型中,除非这种类型在整个代码库中被广泛使用。
func main() {
fmt.Println("hello world")
}
也许你想使用正则表达式,但需要转换为字符串并导入strconv… 😊 请提供更多关于你想要实现的信息!!
package main
import (
"fmt"
"regexp"
"strconv"
)
func main() {
arg := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
for _, v := range arg {
// convert to string
s := strconv.Itoa(v)
// create a regex expression
var myRegex = regexp.MustCompile("^[1|3]$|^13$")
// return your regex test
fmt.Println(myRegex.MatchString(s))
// You can use if, switch to check return is true
}
}
我不太确定你们所说的Go语言没有枚举常量是什么意思。它们的工作方式确实不像Java的enum那样不能与int相互转换,但它们在某种程度上类似于C、C++和C#中的enum。
这里有一个C语言的例子,你可以隐式地将一个整数常量转换为enum(或者应该叫“转换”?我不是语言专家):https://cplayground.com/?p=dog-fly-caribou 在C++和C#中你也可以做同样的事情,但你必须显式地进行转换。
Go语言也是如此:由于Go常量的工作方式,你可以像在C语言中一样将整数常量赋值给一个“enum类型”的变量,但是你不能将一个非常量的int值在没有转换的情况下赋值给Go的“enum类型”变量。
我推荐Dean_Davidson建议的OneOrThree“enum类型”,除非你需要在变量被赋值时验证其状态是否属于n个可能状态之一。但如果确实是这种情况,我很想看看具体的场景。
我实际上是想指出,Go 确实拥有枚举常量。不同语言的语法糖有所不同,而像 Rust 这样的语言对枚举是什么提供了全新的诠释。例如,我是通过 .NET 接触到 Go 的,以下是 C# 中 OneOrThree 的一个示例:
using System;
enum OneOrThree
{
One = 1,
Three = 3,
Both = 4
}
public class Program
{
public static void Main()
{
// 一切正常
doSomething(OneOrThree.One);
// 也没问题
var both = (OneOrThree)4;
doSomething(both);
// 输出 5
var bad = (OneOrThree)5;
doSomething(bad);
}
static void doSomething(OneOrThree arg)
{
Console.WriteLine(arg);
}
}
![]()
再次强调,人机工程学略有不同,但它与 Go 中的实现非常相似,并且默认情况下两者都将底层值存储为 int 常量:
默认情况下,枚举成员的关联常量值类型为
int;它们从零开始,并按照定义文本顺序依次递增。你可以显式指定任何其他整数数值类型作为枚举类型的底层类型。
主要区别在于,在 .NET 中,枚举实际上是继承自 System.Enum 的类。因此,我想如果你希望功能更相似,可以为你的枚举声明一个单独的包——但这在我看来似乎是多余的。
我可以想到几种实现方法。我本来打算用枚举来写一个回复,但@skillian已经很好地涵盖了这一点。对于其他选项,你可以简单地声明一个基于int的简单类型,并使用常量来表示你的值,但这种方法并不安全:
type OneOrThree int
const (
One OneOrThree = 1
Three OneOrThree = 3
Both OneOrThree = 4
)
func main() {
// 开发者知道是怎么回事!
doSomething(One)
doSomething(Three)
doSomething(Both)
// 哎呀...
doSomething(5)
}
func doSomething(arg OneOrThree) {
fmt.Println(arg)
}
https://play.golang.org/p/vgwjKisCDee
然而,根据我的经验,对于内部使用来说,这种方法是可以接受的,因为其意图相当明确。这个值来自哪里?是来自像向API发送请求这样的外部源吗?你的函数是导出的吗?这些问题可能会影响你的设计。如果你需要安全性,并且/或者这是一个要导出的内容,一个简单的选择是验证一个整数数组:
// DoSomething 接受一个包含值1、3或两者的数组。
// 如果参数超出范围,将返回错误。
func DoSomething(arg []int) error {
if len(arg) == 0 {
return errors.New("arg must contain a value")
}
if len(arg) > 2 {
return errors.New("arg can only contain two values")
}
for _, v := range arg {
if v != 1 && v != 3 {
return errors.New("arg can only contain 1 or 3")
}
}
fmt.Println("OK value:", arg)
return nil
}
https://play.golang.org/p/vQiKhWX-7Il
总之,在不了解更多关于你的用例的情况下,很难给出更多建议。但希望这能给你一些启发。
另请参阅:
在Go语言中,可以通过自定义类型和常量来实现带预定义选项列表的变量。以下是几种实现方式:
1. 使用类型别名和常量
type Option int
const (
Option1 Option = 1
Option3 Option = 3
OptionBoth Option = 13 // 或使用其他值表示"两者"
)
func processOption(opt Option) {
switch opt {
case Option1:
fmt.Println("选择了选项1")
case Option3:
fmt.Println("选择了选项3")
case OptionBoth:
fmt.Println("选择了两者")
default:
fmt.Println("无效选项")
}
}
func main() {
var myOption Option = Option1
processOption(myOption) // 输出: 选择了选项1
// 尝试赋值无效值会编译通过,但运行时可以验证
// myOption = 5 // 编译通过,但不符合业务逻辑
}
2. 使用iota和位掩码(如果"两者"表示同时选择1和3)
type Options uint8
const (
Option1 Options = 1 << iota // 1
Option3 // 2
)
const (
OptionBoth = Option1 | Option3 // 3
)
func main() {
var opts Options = Option1
// 检查是否包含某个选项
if opts&Option1 != 0 {
fmt.Println("包含选项1")
}
// 设置多个选项
opts = Option1 | Option3
fmt.Printf("当前选项值: %d\n", opts) // 输出: 3
}
3. 使用字符串枚举
type Selection string
const (
One Selection = "1"
Three Selection = "3"
Both Selection = "both"
)
func validateSelection(s Selection) bool {
switch s {
case One, Three, Both:
return true
default:
return false
}
}
func main() {
var choice Selection = Both
if validateSelection(choice) {
fmt.Printf("有效选择: %s\n", choice)
}
}
4. 使用结构体封装验证
type RestrictedOption struct {
value int
}
func NewRestrictedOption(v int) (*RestrictedOption, error) {
validOptions := map[int]bool{1: true, 3: true, 13: true}
if !validOptions[v] {
return nil, fmt.Errorf("无效选项: %d", v)
}
return &RestrictedOption{value: v}, nil
}
func (ro *RestrictedOption) Value() int {
return ro.value
}
func main() {
opt, err := NewRestrictedOption(3)
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Printf("选项值: %d\n", opt.Value())
}
第一种方式最简洁,通过类型系统限制变量的取值范围,配合switch语句可以确保处理所有预定义选项。如果"两者"需要表示同时包含1和3的概念,第二种位掩码方式更合适。


