Tarkibga o'tish

Go’da enum va iota

Go’da alohida enum kalit so‘zi yo‘q. Enumga o‘xshash qiymatlar nomlangan tur va konstantalar bilan yaratiladi. iota esa const guruhi ichida ketma-ket sonlarni yozishni ixchamlashtiradi.

Nomlangan tur va konstantalar

package main

import "fmt"

type Status int

const (
    StatusUnknown Status = iota
    StatusPending
    StatusProcessing
    StatusCompleted
)

func main() {
    status := StatusProcessing
    fmt.Println(status)
    fmt.Println(status == StatusCompleted)
}

Natija:

2
false

Status nomlangan tur bo‘lgani uchun koddagi ma’no oddiy intdan aniqroq. StatusUnknownni nol qiymatga qo‘yish foydali: var status Status tasodifan haqiqiy biznes holatini bildirmaydi.

iota qanday ishlaydi?

iota har bir const guruhida 0 dan boshlanadi va har bir ConstSpec satrida bittaga oshadi. Ifoda yozilmagan satr oldingi ifoda va uning turini takrorlaydi:

const (
    A = iota + 1 // 1
    B            // 2
    C            // 3
)

Bir satrda bir nechta konstanta bo‘lsa, ular uchun iota bir xil bo‘ladi. _ orqali ayrim qiymatni tashlab ketish mumkin:

type Size uint64

const (
    _  Size = 1 << (10 * iota)
    KB
    MB
    GB
)

Bu yerda birinchi satr _ga beriladi, keyingi qiymatlar mos ravishda 1024, 1048576 va 1073741824 bo‘ladi.

Matn ko‘rinishini berish

Nomlangan turga String metodi qo‘shilsa, fmt uni o‘qilishi qulay ko‘rinishda chiqaradi:

package main

import "fmt"

type Status int

const (
    StatusUnknown Status = iota
    StatusPending
    StatusProcessing
    StatusCompleted
)

func (s Status) String() string {
    switch s {
    case StatusUnknown:
        return "unknown"
    case StatusPending:
        return "pending"
    case StatusProcessing:
        return "processing"
    case StatusCompleted:
        return "completed"
    default:
        return fmt.Sprintf("Status(%d)", s)
    }
}

func main() {
    fmt.Println(StatusProcessing)
    fmt.Println(Status(99))
}

Natija:

processing
Status(99)

default noma’lum qiymatni yashirmaydi. Bu log va diagnostikada foydali. Katta enumlar uchun String metodini generatsiya qiluvchi vositalar ishlatilishi mumkin, ammo generatsiya natijasi repozitoriy qoidalariga muvofiq boshqariladi.

Enum yopiq to‘plam emas

Muhim farq: nomlangan son turiga istalgan mos sonni ochiq konvertatsiya qilish mumkin — Status(99) kompilyatsiyadan o‘tadi. Demak, Go’dagi bu usul qiymatlarni mutlaq cheklamaydi. Tashqi input, JSON yoki database qiymatini qabul qilganda validatsiya kerak:

func (s Status) Valid() bool {
    return s >= StatusUnknown && s <= StatusCompleted
}

Konstantalarni database yoki tarmoq protokolida saqlasangiz, o‘rtaga yangi iota qiymati qo‘shish keyingi raqamlarni siljitadi. Bunday formatlarda aniq sonlarni yozish yoki faqat oxiriga yangi qiymat qo‘shish xavfsizroq.

Bit bayroqlar

iota bitmask yaratishda ham ishlatiladi:

type Permission uint8

const (
    PermissionRead Permission = 1 << iota
    PermissionWrite
    PermissionDelete
)

func has(value, permission Permission) bool {
    return value&permission != 0
}

Bu oddiy ketma-ket enum emas: qiymatlar 1, 2, 4 bo‘lib, | bilan birlashtiriladi. Masalan, PermissionRead | PermissionWrite ikkala ruxsatni saqlaydi.

Xulosa

  • Go’da enum alohida til konstruksiyasi emas; nomlangan tur va konstantalar ishlatiladi.
  • iota const guruhidagi satrlar bo‘yicha oshadi va har yangi guruhda nolga qaytadi.
  • Nol qiymatni Unknown holatiga ajratish xavfsiz dizayn beradi.
  • Istalgan sonni nomlangan turga konvertatsiya qilish mumkin, shu sabab tashqi qiymat validatsiya qilinadi.
  • Barqaror tashqi formatlarda iota raqamlarining siljishiga ehtiyot bo‘lish kerak.