GoDasturchi
Find or Nil

Find or Nil

Topish yoki nil

Siz *Userni undan o'qishdan oldin nil uchun himoyalashni bilasiz. Bu dars o'sha shartnomaning boshqa tomoni: pointerni qaytaradigan topuvchini yozish.

Ma'lumot slicada yashaganda, *Pointers Into Slices* darsidagi nusxa tuzog'i yangi burilish bilan qaytadi. Pointer funksiyani tark etadi, va chaqiruvchi undan keyinroq, uni yaratgan sikl allaqachon yo'qolgandan ancha keyin yozadi.

example.go
type Account struct {
	ID      string
	Balance int
}

// XATO: nusxaga pointer qaytaradi, shuning uchun chaqiruvchining yozuvi yo'qoladi
func Find(accounts []Account, id string) *Account {
	for _, acc := range accounts {
		if acc.ID == id {
			return &acc
		}
	}
	return nil
}

accounts := []Account{{ID: "a1", Balance: 100}}
a := Find(accounts, "a1")
a.Balance += 50
fmt.Println(accounts[0].Balance) // 100, 150 emas

Value-range sikli har bir elementni accga nusxalaydi, shuning uchun &acc slicega emas, nusxaga ishora qiladi. Joyida o'zgartiradigan sikl ichida bo'lganida, o'zgarish keyingi o'tishda yo'qolib ketganini ko'rgan bo'lardingiz.

Bu yerda esa jimroq va yomonroq: pointer funksiyani hali o'sha nusxaga qaratilgan holda tark etadi, chaqiruvchining a.Balance += 50si hech kim ushlab turmagan xotiraga tushadi, va slice hech qachon o'zgarmaydi.

Tuzatish

Qaytaradigan manzil tub massivga ishora qilishi uchun indeks bo'yicha aylaning:

example.go
func Find(accounts []Account, id string) *Account {
	for i := range accounts {
		if accounts[i].ID == id {
			return &accounts[i]
		}
	}
	return nil
}

accounts := []Account{{ID: "a1", Balance: 100}}
a := Find(accounts, "a1")
a.Balance += 50
fmt.Println(accounts[0].Balance) // 150

Endi nolmas qaytish — haqiqiy hisobga jonli tutqich. Moslik uchun &accounts[i], moslik topilmasa nil.

>_ Exercise

LowestStockni amalga oshiring. U eng kam zaxiraga ega mahsulotga ishora qiluvchi *Item qaytaradi, shunda chaqiruvchi uning Stockiga qo'shib uni to'ldirishi mumkin. Pointer haqiqiy sliceга ishora qilishi kerak: chaqiruvchining yozuvi nusxaga emas, asl mahsulotga tushishi kerak.

Talablar

  • Eng past Stockga ega mahsulotga pointer qaytaring
  • Chaqiruvchi qaytarilgan pointer orqali qiladigan yozuv o'sha mahsulotni asl slice ichida o'zgartirishi kerak
  • Slicada kamida bitta mahsulot borligini taxmin qilishingiz mumkin

Stuck? Reveal a hint to help you.

Hints (0/4)

Key Takeaway

Key Takeaway:

Topuvchi slicega jonli pointer uchun &slice[i], moslik topilmasa nil qaytaradi. Value-range'dan &loopvar qaytarish allaqachon yo'qolgan nusxaga pointer beradi.

NEXT UP

Where Memory Lives

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Find or Nil

Topish yoki nil

Siz *Userni undan o'qishdan oldin nil uchun himoyalashni bilasiz. Bu dars o'sha shartnomaning boshqa tomoni: pointerni qaytaradigan topuvchini yozish.

Ma'lumot slicada yashaganda, *Pointers Into Slices* darsidagi nusxa tuzog'i yangi burilish bilan qaytadi. Pointer funksiyani tark etadi, va chaqiruvchi undan keyinroq, uni yaratgan sikl allaqachon yo'qolgandan ancha keyin yozadi.

example.go
type Account struct {
	ID      string
	Balance int
}

// XATO: nusxaga pointer qaytaradi, shuning uchun chaqiruvchining yozuvi yo'qoladi
func Find(accounts []Account, id string) *Account {
	for _, acc := range accounts {
		if acc.ID == id {
			return &acc
		}
	}
	return nil
}

accounts := []Account{{ID: "a1", Balance: 100}}
a := Find(accounts, "a1")
a.Balance += 50
fmt.Println(accounts[0].Balance) // 100, 150 emas

Value-range sikli har bir elementni accga nusxalaydi, shuning uchun &acc slicega emas, nusxaga ishora qiladi. Joyida o'zgartiradigan sikl ichida bo'lganida, o'zgarish keyingi o'tishda yo'qolib ketganini ko'rgan bo'lardingiz.

Bu yerda esa jimroq va yomonroq: pointer funksiyani hali o'sha nusxaga qaratilgan holda tark etadi, chaqiruvchining a.Balance += 50si hech kim ushlab turmagan xotiraga tushadi, va slice hech qachon o'zgarmaydi.

Tuzatish

Qaytaradigan manzil tub massivga ishora qilishi uchun indeks bo'yicha aylaning:

example.go
func Find(accounts []Account, id string) *Account {
	for i := range accounts {
		if accounts[i].ID == id {
			return &accounts[i]
		}
	}
	return nil
}

accounts := []Account{{ID: "a1", Balance: 100}}
a := Find(accounts, "a1")
a.Balance += 50
fmt.Println(accounts[0].Balance) // 150

Endi nolmas qaytish — haqiqiy hisobga jonli tutqich. Moslik uchun &accounts[i], moslik topilmasa nil.

>_ Exercise

LowestStockni amalga oshiring. U eng kam zaxiraga ega mahsulotga ishora qiluvchi *Item qaytaradi, shunda chaqiruvchi uning Stockiga qo'shib uni to'ldirishi mumkin. Pointer haqiqiy sliceга ishora qilishi kerak: chaqiruvchining yozuvi nusxaga emas, asl mahsulotga tushishi kerak.

Talablar

  • Eng past Stockga ega mahsulotga pointer qaytaring
  • Chaqiruvchi qaytarilgan pointer orqali qiladigan yozuv o'sha mahsulotni asl slice ichida o'zgartirishi kerak
  • Slicada kamida bitta mahsulot borligini taxmin qilishingiz mumkin

Stuck? Reveal a hint to help you.

Hints (0/4)

Key Takeaway

Key Takeaway:

Topuvchi slicega jonli pointer uchun &slice[i], moslik topilmasa nil qaytaradi. Value-range'dan &loopvar qaytarish allaqachon yo'qolgan nusxaga pointer beradi.

NEXT UP

Where Memory Lives