Darsliklar Go Lang Type Assertion va Type Switch

Go Lang Go Lang Type Assertion va Type Switch

Type Assertioninterface{} (yoki any) ichida saqlangan qiymatning aniq turini olib chiqish usuli. Interfeys o’zi turdan mustaqil bo’lgani uchun, ichidagi haqiqiy qiymat bilan ishlash uchun uni “qaytadan aniqlash” kerak bo’ladi.

Type Assertionqiymat.(Tur) yozuvi orqali interfeys ichidagi qiymatning aniq turi ekanini “tasdiqlash”. Ikki xavfsizlik darajasida yoziladi: xavfli (bitta natija) va xavfsiz (ikkita natija, comma-ok).

Xavfsiz shakl — comma-ok

Ikki qiymat qaytariladigan shaklda, mos kelmasa dastur qulamaydi — ikkinchi qiymat shunchaki false bo’ladi:

package main

import "fmt"

func main() {
    var i interface{} = "salom"

    s, ok := i.(string)
    fmt.Println(s, ok)

    n, ok2 := i.(int)
    fmt.Println(n, ok2)
}
salom true
0 false

i.(string)i chindan string ekanini tasdiqladi, oktrue. i.(int) esa mos kelmadi: nintning zero value’si (0), ok2false. Muhimi: hech qanday panic yuz bermadi.

Xavfli shakl — bitta natija

Agar faqat qiymatning o’zi so’ralsa (ikkinchi natijasiz), mos kelmagan holatda dastur qulaydi:

package main

import "fmt"

func main() {
    var i interface{} = "salom"
    n := i.(int)
    fmt.Println(n)
}
panic: interface conversion: interface {} is string, not int

goroutine 1 [running]:
main.main()
    ...
exit status 2

i.(int)i aslida string bo’lgani uchun mos kelmadi, va bu safar ok bo’lmagani sabab Go buni jiddiy xato deb hisoblab, dasturni to’xtatdi. Shu sabab manba tashqaridan (masalan, tarmoqdan) kelgan qiymatlar ustida deyarli har doim xavfsiz — comma-ok — shakli ishlatiladi.

Type Switch — bir nechta turni ketma-ket tekshirish

Bitta qiymatni bir nechta mumkin bo’lgan tur bilan solishtirish uchun maxsus switch v := qiymat.(type) shakli ishlatiladi:

package main

import "fmt"

func aniqla(qiymat interface{}) {
    switch v := qiymat.(type) {
    case int:
        fmt.Println("butun son:", v)
    case string:
        fmt.Println("satr:", v)
    case bool:
        fmt.Println("mantiqiy:", v)
    default:
        fmt.Println("boshqa tur")
    }
}

func main() {
    aniqla(42)
    aniqla("salom")
    aniqla(true)
    aniqla(3.14)
}
butun son: 42
satr: salom
mantiqiy: true
boshqa tur

qiymat.(type) — oddiy type assertion’dan farqli, faqat switch ichida ishlaydi. Har bir caseda v avtomatik o’sha casening turiga ega bo’ladi (masalan, case int: ichida v — allaqachon int, qo’shimcha o’girish shart emas). 3.14 (float64) hech qaysi casega mos kelmadi, shuning uchun default ishladi.

Amaliy qo’llanilish — turlicha ma’lumotni qayta ishlash

Type switch ayniqsa tashqaridan (masalan, JSON’dan) kelgan, turi oldindan noma’lum ma’lumot bilan ishlashda foydali:

package main

import "fmt"

func hajm(qiymat interface{}) int {
    switch v := qiymat.(type) {
    case []int:
        return len(v)
    case string:
        return len(v)
    case map[string]int:
        return len(v)
    default:
        return -1
    }
}

func main() {
    fmt.Println(hajm([]int{1, 2, 3}))
    fmt.Println(hajm("salom"))
    fmt.Println(hajm(map[string]int{"a": 1, "b": 2}))
    fmt.Println(hajm(42))
}
3
5
2
-1

Bitta hajm funksiyasi to’rtta butunlay boshqa turdagi qiymatning “hajmi” nima ekanini to’g’ri aniqladi — har biri uchun len()ning ma’nosi boshqacha, lekin type switch buni bir joyda toza boshqaradi.