Heim  >  Artikel  >  Backend-Entwicklung  >  So verwenden Sie Iota in Go

So verwenden Sie Iota in Go

藏色散人
藏色散人nach vorne
2021-04-29 11:52:432102Durchsuche

Die folgende Tutorial-Kolumne von golang wird Ihnen die Verwendung von Iota in Go vorstellen. Ich hoffe, dass es Freunden in Not hilfreich sein wird!

Einführung

Die Go-Sprache unterstützt das Aufzählungsschlüsselwort tatsächlich nicht direkt. Im Allgemeinen implementieren wir Aufzählungsfunktionen durch const + iota. const + iota 实现枚举的能力。

有人要问了,为什么一定要使用枚举呢?stackoverflow 上有一个高赞的回答,如下:

You should always use enums when a variable (especially a method parameter) can only take one out of a small set of possible values. Examples would be things like type constants (contract status: “permanent”, “temp”, “apprentice”), or flags (“execute now”, “defer execution”). If you use enums instead of integers (or String codes), you increase compile-time checking and avoid errors from passing in invalid constants, and you document which values are legal to use.BTW, overuse of enums might mean that your methods do too much (it’s often better to have several separate methods, rather than one method that takes several flags which modify what it does), but if you have to use flags or type codes, enums are the way to go.

简单翻译一下, 两点很重要。

  • 当一个变量(尤其是方法参数) 只能从一小部分可能的值中取出一个时,理应使用枚举。
    例如类型常量(合同状态:永久、临时工、学徒), 或者在做任务程序时,是立即执行还是延迟执行的标记。
  • 如果使用枚举而不是整形,则会增加编译时的检查,避免错误无效值的传入,记录哪些值是合法使用的。

如何实现枚举

iota 是 Go 中预声明的一个特殊常量。它会被预声明为0,但是它的值在编译阶段并非是固定的,当预声明的 iota 出现在一个常量声明中的时候,它的值在第n个常量描述中的值为n(从0开始)。所以它只在同类型多个常量声明的情况下才显得有意义。

比如,大家都了解的电商,订单系统一定会涉及到订单状态的流转。那么这时候,我们一般可以这样做:

package mainimport "fmt"type OrderStatus intconst (
  Cancelled OrderStatus = iota //订单已取消 0  NoPay OrderStatus = iota //未支付  1  PendIng OrderStatus = iota // 未发货 2  Delivered OrderStatus = iota // 已发货 3  Received OrderStatus = iota // 已收货 4)func main() {
  fmt.Println(Cancelled, NoPay) // 打印:0,1}

当然,这样看着好麻烦。其实,其他常量可以重复上一行 iota 表达式,我们可以改成这样。

package mainimport "fmt"type OrderStatus intconst (
  Cancelled OrderStatus = iota //订单已取消 0  NoPay //未支付 1  PendIng // 未发货 2  Delivered // 已发货 3  Received // 已收货 4)func main() {
  fmt.Println(Cancelled, NoPay) // 打印:0,1}

有人会用 0 的值来表示状态吗?一般都不会,我们想以1开头,那么可以这样。

package mainimport "fmt"type OrderStatus intconst (
  Cancelled OrderStatus = iota+1 //订单已取消 1
  NoPay //未支付 2  PendIng // 未发货 3  Delivered // 已发货 4  Received // 已收货 5)func main() {
  fmt.Println(Cancelled, NoPay) // 打印:1,2}

我们还想在 Delivered 后跳过一个数字,才是 Received 的值,也就是 Received=6,那么可以借助 _ 符号。

package mainimport "fmt"type OrderStatus intconst (
  Cancelled OrderStatus = iota+1 //订单已取消 1
  NoPay //未支付 2  PendIng // 未发货 3  Delivered // 已发货 4  _
 Received // 已收货 6)func main() {
  fmt.Println(Received) // 打印:6}

顺着来可以,倒着当然也行。

package mainimport "fmt"type OrderStatus intconst (
  Max = 5)const (
  Received OrderStatus = Max - iota // 已收货  5  Delivered // 已发货 4  PendIng // 未发货 3  NoPay //未支付 2  Cancelled //订单已取消 1)func main() {
  fmt.Println(Received,Delivered) // 打印:5,4}

你还可以使用位运算,比如在 go 源码中的包 sync 中的锁上面有这么一段代码。

const (
 mutexLocked = 1 << iota  //1<<0 mutexWoken               //1<<1 mutexStarving            //1<<2 mutexWaiterShift = iota  //3
)

func main() {
 fmt.Println("mutexLocked的值",mutexLocked) //打印:1 fmt.Println("mutexWoken的值",mutexWoken) //打印:2 fmt.Println("mutexStarving的值",mutexStarving) //打印:4 fmt.Println("mutexWaiterShift的值",mutexWaiterShift) // 打印:3}

可能有人平常是直接定义常量值或者用字符串来表示的。

比如,上面这些我完全可以用 string 来表示,我还真见过用字符串来表示订单状态的。

package main

import "fmt"

const (
  Cancelled = "cancelled"  NoPay = "noPay"  PendIng = "pendIng"  Delivered = "delivered"  Received = "received")

var OrderStatusMsg = map[string]string{
  Cancelled: "订单已取消",
  NoPay:     "未付款",
  PendIng:   "未发货",
  Delivered: "已发货",
  Received:  "已收货",
}

func main() {
  fmt.Println(OrderStatusMsg[Cancelled])
}

或者直接定义整形常量值。

package main

import "fmt"

const (
  Cancelled = 1  NoPay = 2  PendIng = 3  Delivered = 4  Received = 5)

var OrderStatusMsg = map[int]string{
  Cancelled: "订单已取消",
  NoPay:     "未付款",
  PendIng:   "未发货",
  Delivered: "已发货",
  Received:  "已收货",
}

func main() {
  fmt.Println(OrderStatusMsg[Cancelled])
}

其实上述两种都可以,但是相比之下使用 iota 更有优势。

  • 能保证一组常量的唯一性,人工定义的不能保证。
  • 可以为一组动作分享同一种行为。
  • 避免无效值。
  • 提高代码阅读性以及维护。

延伸

按照上面我们所演示的,最后我们可以这样操作。

package main

import (
 "fmt")

type OrderStatus int

const (
  Cancelled OrderStatus = iota + 1 //订单已取消 1  NoPay //未支付 2  PendIng // 未发货 3  Delivered // 已发货 4  Received // 已收货 5)

//公共行为 赋予类型 String() 函数,方便打印值含义
func (order OrderStatus) String() string { return [...]string{"cancelled", "noPay", "pendIng", "delivered", "received"}[order-1]
}

//创建公共行为 赋予类型 int 函数 EnumIndex()
func (order OrderStatus) EnumIndex() int { return int(order)
}

func main() {
 var order OrderStatus = Received
  fmt.Println(order.String())    // 打印:received
  fmt.Println(order.EnumIndex()) // 打印:5
}

总结

这篇文章主要介绍了 Golang 中对 iota

Jemand fragt sich vielleicht: Warum müssen wir Aufzählungen verwenden? Auf stackoverflow gibt es eine hochgelobte Antwort wie folgt:

Sie sollten Aufzählungen immer dann verwenden, wenn eine Variable (insbesondere ein Methodenparameter) nur einen aus einer kleinen Menge möglicher Werte annehmen kann . Beispiele wären Dinge wie Typkonstanten (Vertragsstatus: „permanent“, „temp“, „apprentice“) oder Flags („jetzt ausführen“, „Ausführung verzögern“), wenn Sie Aufzählungen anstelle von Ganzzahlen (oder String-Codes) verwenden ), erhöhen Sie die Überprüfung bei der Kompilierung und vermeiden Fehler durch die Übergabe ungültiger Konstanten, und Sie dokumentieren, welche Werte zulässig sind. Übrigens kann eine übermäßige Verwendung von Aufzählungen dazu führen, dass Ihre Methoden zu viel bewirken (es ist oft besser, mehrere separate zu verwenden). Methoden, statt einer Methode, die mehrere Flags benötigt, die ihre Funktion ändern), aber wenn Sie Flags oder Typcodes verwenden müssen, sind Aufzählungen die richtige Wahl.
Eine kurze Übersetzung, zwei Punkte sind sehr wichtig . 🎜
  • Wenn eine Variable (insbesondere ein Methodenparameter) nur einen von wenigen möglichen Werten annehmen kann, sollte eine Aufzählung verwendet werden.
    Zum Beispiel Typkonstanten (Vertragsstatus: unbefristet, Zeitarbeiter, Lehrling) oder ein Flag für die sofortige oder verzögerte Ausführung bei der Ausführung eines Aufgabenprogramms.
  • Wenn Sie Aufzählungen anstelle von Ganzzahlen verwenden, werden Überprüfungen zur Kompilierungszeit hinzugefügt, um zu verhindern, dass falsche ungültige Werte übergeben werden, und um aufzuzeichnen, welche Werte legal verwendet werden.
🎜🎜🎜So implementieren Sie Aufzählungen🎜🎜iota ist eine spezielle Konstante, die in Go vordeklariert ist. Es wird als 0 vordeklariert, aber sein Wert wird in der Kompilierungsphase nicht festgelegt. Wenn das vordeklarierte iota in einer Konstantendeklaration erscheint, wird sein Wert in der n-ten Konstante beschrieben. Die Werte in sind n (beginnend bei 0). Es macht also nur dann Sinn, wenn mehrere Konstantendeklarationen desselben Typs vorhanden sind. 🎜🎜Wie zum Beispiel jeder über E-Commerce weiß, wird das Bestellsystem definitiv den Fluss des Bestellstatus einbeziehen. Zu diesem Zeitpunkt können wir also im Allgemeinen Folgendes tun: 🎜rrreee🎜Natürlich sieht das sehr problematisch aus. Tatsächlich können andere Konstanten den iota-Ausdruck in der vorherigen Zeile wiederholen, und wir können ihn in diesen ändern. 🎜rrreee🎜Kann jemand den Wert 0 verwenden, um den Status darzustellen? Im Allgemeinen nicht, wir wollen mit 1 beginnen, also ist das in Ordnung. 🎜rrreee🎜Wir möchten auch eine Zahl nach Delivered überspringen, die der Wert von Received ist, also Received=6, dann wir kann das Symbol _ verwenden. 🎜rrreee🎜Es ist in Ordnung, es nebenbei zu machen, und natürlich ist es auch in Ordnung, es rückwärts zu machen. 🎜rrreee🎜Sie können auch Bitoperationen verwenden, zum Beispiel gibt es einen solchen Code für die Sperre im Paket sync im Go-Quellcode. 🎜rrreee🎜Vielleicht definieren manche Leute konstante Werte normalerweise direkt oder verwenden Zeichenfolgen, um sie darzustellen. 🎜🎜Zum Beispiel kann ich string verwenden, um das Obige darzustellen. Ich habe tatsächlich Zeichenfolgen gesehen, die zur Darstellung des Bestellstatus verwendet werden. 🎜rrreee🎜Oder definieren Sie direkt den ganzzahligen Konstantenwert. 🎜rrreee🎜Tatsächlich ist beides möglich, aber die Verwendung von iota hat noch mehr Vorteile. 🎜
  • Die Eindeutigkeit einer Menge von Konstanten kann garantiert werden, eine manuelle Definition jedoch nicht.
  • Dasselbe Verhalten kann für eine Gruppe von Aktionen verwendet werden.
  • Ungültige Werte vermeiden.
  • Verbessern Sie die Lesbarkeit und Wartung des Codes.
🎜🎜🎜Erweiterung🎜🎜Befolgen Sie, was wir oben gezeigt haben, und endlich können wir dies tun. 🎜rrreee🎜Zusammenfassung🎜🎜Dieser Artikel stellt hauptsächlich die Verwendung von iota in Golang vor und warum wir es verwenden sollten. 🎜🎜Ich weiß nicht, welche Tricks Sie normalerweise für diese Art von Szene verwenden. Bitte hinterlassen Sie unten eine Nachricht zum Austausch. 🎜                                                                                                           

Das obige ist der detaillierte Inhalt vonSo verwenden Sie Iota in Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:learnku.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen