GoDasturchi
Scope and Shadowing

Scope and Shadowing

Ko'lam (scope) va soyalash (shadowing)

Har bir o'zgaruvchi ma'lum bir ko'lam (scope)da yashaydi — odatda uni o'rab turgan { } bloki ichida. Muammo shundaki, ichki blokda := bilan tashqaridagi bilan bir xil nomli yangi o'zgaruvchi yaratish mumkin — bu tashqi o'zgaruvchini soyalaydi (shadow), uni o'zgartirmaydi.

example.go
func ProcessBroken() (int, error) {
    value, err := FetchValue()
    if err != nil {
        return 0, err
    }

    if value > 0 {
        value, err := FetchUpdatedValue()  // XATO: yangi, soyalangan value!
        if err != nil {
            return 0, err
        }
        _ = value  // bu faqat if bloki ichida ko'rinadi
    }

    return value, nil  // tashqi value hali eski qiymatda
}

Bu — Go'da eng ko'p uchraydigan nozik xatolardan biri, chunki := bilan yozilgan kod to'g'ri ko'rinadi va hatto kompilyatsiya bo'ladi. Muammo shu: if bloki ichidagi value, err := yangi value va errni e'lon qiladi (chunki chap tomonda kamida bitta yangi nom bo'lsa, := barcha nomlarni qayta e'lon qiladi), tashqaridagi value esa o'zgarishsiz qoladi.

example.go
if value > 0 {
    v2, err := FetchUpdatedValue()
    if err != nil {
        return 0, err
    }
    value = v2  // TO'G'RI: = bilan tashqi value'ni o'zgartiradi
}

To'g'ri yechim — yangi o'zgaruvchiga boshqa nom berish (v2), so'ngra uni tashqi valuega = (yangi e'londirmasdan, oddiy tayinlash) bilan yozish.

>_ Exercise

Berilgan FetchValue, FetchUpdatedValue va soyalash xatosi bo'lgan ProcessBrokendan foydalanib, ProcessFixed() (int, error) funksiyasini yozing — u xuddi shu mantiqni bajaradi, lekin soyalashsiz: ichki natijani v2 deb nomlab, tashqi valueni = bilan yangilang.

Stuck? Reveal a hint to help you.

Hints (0/4)

Key Takeaway

Key Takeaway:

:= chap tomonidagi kamida bitta nom yangi bo'lsa, barcha nomlarni shu blok ko'lamida qayta e'lon qiladi — bu tashqi o'zgaruvchini soyalab, uni o'zgartirmasdan qoldirishi mumkin. Mavjud o'zgaruvchini haqiqatan yangilash uchun oddiy = (tayinlash) ishlatiladi, yangi nom bilan emas.

Finish
OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Scope and Shadowing

Ko'lam (scope) va soyalash (shadowing)

Har bir o'zgaruvchi ma'lum bir ko'lam (scope)da yashaydi — odatda uni o'rab turgan { } bloki ichida. Muammo shundaki, ichki blokda := bilan tashqaridagi bilan bir xil nomli yangi o'zgaruvchi yaratish mumkin — bu tashqi o'zgaruvchini soyalaydi (shadow), uni o'zgartirmaydi.

example.go
func ProcessBroken() (int, error) {
    value, err := FetchValue()
    if err != nil {
        return 0, err
    }

    if value > 0 {
        value, err := FetchUpdatedValue()  // XATO: yangi, soyalangan value!
        if err != nil {
            return 0, err
        }
        _ = value  // bu faqat if bloki ichida ko'rinadi
    }

    return value, nil  // tashqi value hali eski qiymatda
}

Bu — Go'da eng ko'p uchraydigan nozik xatolardan biri, chunki := bilan yozilgan kod to'g'ri ko'rinadi va hatto kompilyatsiya bo'ladi. Muammo shu: if bloki ichidagi value, err := yangi value va errni e'lon qiladi (chunki chap tomonda kamida bitta yangi nom bo'lsa, := barcha nomlarni qayta e'lon qiladi), tashqaridagi value esa o'zgarishsiz qoladi.

example.go
if value > 0 {
    v2, err := FetchUpdatedValue()
    if err != nil {
        return 0, err
    }
    value = v2  // TO'G'RI: = bilan tashqi value'ni o'zgartiradi
}

To'g'ri yechim — yangi o'zgaruvchiga boshqa nom berish (v2), so'ngra uni tashqi valuega = (yangi e'londirmasdan, oddiy tayinlash) bilan yozish.

>_ Exercise

Berilgan FetchValue, FetchUpdatedValue va soyalash xatosi bo'lgan ProcessBrokendan foydalanib, ProcessFixed() (int, error) funksiyasini yozing — u xuddi shu mantiqni bajaradi, lekin soyalashsiz: ichki natijani v2 deb nomlab, tashqi valueni = bilan yangilang.

Stuck? Reveal a hint to help you.

Hints (0/4)

Key Takeaway

Key Takeaway:

:= chap tomonidagi kamida bitta nom yangi bo'lsa, barcha nomlarni shu blok ko'lamida qayta e'lon qiladi — bu tashqi o'zgaruvchini soyalab, uni o'zgartirmasdan qoldirishi mumkin. Mavjud o'zgaruvchini haqiqatan yangilash uchun oddiy = (tayinlash) ishlatiladi, yangi nom bilan emas.