掌握 Go 中的 ENUM

图片来自 Unsplash 的 Hans-Peter Gauster

假设我们正在构建一个电子商务 API,它将接收多个订单,每个订单流程都有多个状态,例如。并且我们的应用程序接收将存储在数据库中的输入字符串,例如状态为已处理、已接收处理、正在处理或其他导致数据不一致的状态。在这里枚举起着重要作用。

在 Golang 中,枚举与 Java 或 C# 等其他提供内置枚举支持的语言不同,Go 采用了不同的方法。在 Go 中,枚举不是原生语言功能,但开发人员可以使用多种技术来实现类似的功能。

理解枚举

在 Golang 中,枚举(枚举的简称)提供了一种表示一组命名常量的方法。尽管 Go 不像其他一些语言那样具有内置枚举类型,但开发人员可以使用常量或自定义类型模拟类似枚举的行为。让我们讨论一下 Go 中枚举的用途和语法:

客观的

  • 可读性和可维护性:枚举通过为特定值赋予有意义的名称,使代码更易读、更易于理解。这提高了代码的可维护性,因为每个常量的用途变得更容易理解。
  • 类型安全:枚举通过将变量限制为一组预定义的值来帮助强制执行类型安全。这降低了因使用不正确的值而导致运行时错误的可能性。
  • 创建枚举

    在这里我们将逐步讨论如何在 Golang 中创建枚举,以便于理解每个阶段我们将解释我们编写的代码的含义。

    创建新类型

    我们要做的第一件事是为我们需要的枚举创建一个新类型。方法很简单,我们只需要使用关键字,然后跟上类型的名称,这里的名称为**StatusOrder**,然后我们在这里定义类型**无符号整数**,如下所示:

    type StatusOrder uint

    嗯,简单点就好。

    定义常量 ENUM

    有了我们创建的新类型,现在是时候用常量定义一些订单状态了。我们定义类型 **StatusOrder** 作为我们创建的类型,如下所示:

    const (
        Pending StatusOrder = iota
        Processed
        Shipped
        Delivered
        Cancelled
    )

    也许你会问,关键字 `iota` 是什么?这个关键字让 GO 为第一个常量分配一个 0 的值,然后对每个后续常量依次将值增加 1。这让我们更容易,而不是手动一个接一个地定义值。关于 `iota` 你可以在这里阅读。

    函数字符串

    我们下一步要做的事情是创建一个字符串函数,用于表示“StatusOrder”枚举中的每个字符串值。

    func (s StatusOrder) String() string {
        switch s {
        case Pending:
            return "Pending"
        case Processed:
            return "Processed"
        case Shipped:
            return "Shipped"
        case Delivered:
            return "Delivered"
        case Cancelled:
            return "Cancelled"
        default:
            return "Unknown"
        }
    }

    函数名必须是“String”吗?我们将在最后讨论它。

    测试

    现在我们将进行测试,我们将编写的最后一段代码是函数**main**,并在其中借助`fmt`包打印结果。是的。

    func main() {
    
        processed := Processed
        fmt.Printf("Order Status: %s (%d)\n", processed, processed)
    
        pending := Pending
        fmt.Printf("Order Status: %s (%d)\n", pending, pending)
    
    }

    现在可以在这里看到完整的代码。

    当然,我们执行最后一步,就会看到这样的结果:

    Image description

    弗特·斯特林格

    你可能会问,“为什么当我们调用枚举常量时,String 函数也会被调用?”。答案是因为我们使用了“fmt”包。fmt 包明确使用 **fmt.Stringer** 接口来处理实现 String() 方法的类型。因此,如果你不使用 fmt,String() 方法将不会被自动调用。如需更多解释,你可以在此处进行更详细的探索。

    结论

    虽然 Golang 没有提供原生的枚举类型,但我们在这里学到的技术经常用于用 Golang 构建应用程序。而对于类型本身,我们可以自由地使用其他类型,而不仅仅是整数。通过利用这种技术,可读性、易维护性和安全性可以得到显著提高。

    也许你觉得上面解释的有些地方还不够清楚,我们可以在下面的评论栏里讨论。希望对你有帮助👋。

    阅读参考文献

  • 格式
  • 围棋维基:Iota
  • Golang 中的枚举:技术、最佳实践和用例
  • 掌握 Go 中的 ENUM