GoDasturchi
Pointers Into Slices

Pointers Into Slices

Pointerlar slice ichida

Sizning xizmatingiz kechikish namunalarining to'plamini yozib oldi, lekin xato har bir o'qishga qo'shimcha 20ms qo'shib qo'ygan. Siz o'sha 20ms'ni har bir namunadan qaytadan ayirmoqchisiz, shuning uchun oddiy sikl yozasiz:

example.go
samples := []int{120, 145, 98, 200}
for _, s := range samples {
	s -= 20
}
fmt.Println(samples) // [120 145 98 200]

Slice o'zgarishsiz qoldi.

Nega range sikllari o'zgartirmaydi

range sizga har bir elementning yangi nusxasini beradi. ssamples[0]ning nusxasi, keyin samples[1]ning nusxasi, va h.k. sdan ayirish nusxani o'zgartiradi, keyin navbatdagi o'tish uni tashlab yuboradi. Slice hech qachon o'zgarmadi.

Buning o'rniga slice ichiga indekslang:

example.go
for i := range samples {
	samples[i] -= 20
}

samples[i] to'g'ridan-to'g'ri slicening tub massiviga yozadi. O'zgarish har bir element ustida arifmetika kabi inline qilish uchun yetarlicha oddiy bo'lganda shunga murojaat qiling.

Manzil kerak bo'lganda

Ba'zan boshqa funksiya ishni bajaradi. Aytaylik, metrikalar jamoasi shu yordamchini yetkazadi:

example.go
func Calibrate(p *int, offset int) {
	*p -= offset
}

U *int qabul qiladi, shuning uchun unga elementning manzilini berasiz:

example.go
for i := range samples {
	Calibrate(&samples[i], offset)
}

&samples[i] tub massivdagi i elementiga ishora qiladi. Yordamchi o'sha pointer orqali yozadi, va slice o'zgarishni ko'radi.

Kontentni tahrirlash va slicening o'zini qayta belgilash

Slice qiymati allaqachon o'z tub massiviga havolani olib yuradi, shuning uchun funksiya oddiy []int orqali elementlarni tahrirlashi mumkin. Buning uchun *[]int kerak emas. *[]intga faqat funksiya slice header'ining o'zini qayta belgilaganda, masalan uni append bilan kengaytirganda murojaat qiling.

>_ Exercise

Onlayn do'kon mijoz bitta buyurtmada bitta mahsulotdan qancha sotib olishi mumkinligini cheklaydi. Savatchangiz har bir mahsulot uchun sonini ushlab turadi. Hech qanday son shu buyurtma chegarasidan oshmasligi kerak. Ikkala funksiyani yozing:

Signaturalar

example.go
func Limit(qty *int, max int)
func LimitAll(quantities []int, max int)

Talablar

  • Limit *int qabul qiladi va uni faqat maxdan oshsa maxgacha qisqartiradi
  • LimitAll quantitiesdagi har bir element uchun bir marta Limitni chaqiradi, joyida o'zgartirib, qaytish qiymatisiz

Qochish kerak bo'lgan tuzoq

for _, q := range quantities { Limit(&q, max) } slice elementining emas, sikl o'zgaruvchisining manzilini oladi. Buning o'rniga indeks bo'yicha aylaning.

Stuck? Reveal a hint to help you.

Hints (0/5)

Key Takeaway

Key Takeaway:

range sizga har bir elementning nusxasini beradi, shuning uchun slicani o'zgartirish uchun uning haqiqiy elementiga samples[i] orqali indeks bilan yetib borasiz.

NEXT UP

Pointer to Struct

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Pointers Into Slices

Pointerlar slice ichida

Sizning xizmatingiz kechikish namunalarining to'plamini yozib oldi, lekin xato har bir o'qishga qo'shimcha 20ms qo'shib qo'ygan. Siz o'sha 20ms'ni har bir namunadan qaytadan ayirmoqchisiz, shuning uchun oddiy sikl yozasiz:

example.go
samples := []int{120, 145, 98, 200}
for _, s := range samples {
	s -= 20
}
fmt.Println(samples) // [120 145 98 200]

Slice o'zgarishsiz qoldi.

Nega range sikllari o'zgartirmaydi

range sizga har bir elementning yangi nusxasini beradi. ssamples[0]ning nusxasi, keyin samples[1]ning nusxasi, va h.k. sdan ayirish nusxani o'zgartiradi, keyin navbatdagi o'tish uni tashlab yuboradi. Slice hech qachon o'zgarmadi.

Buning o'rniga slice ichiga indekslang:

example.go
for i := range samples {
	samples[i] -= 20
}

samples[i] to'g'ridan-to'g'ri slicening tub massiviga yozadi. O'zgarish har bir element ustida arifmetika kabi inline qilish uchun yetarlicha oddiy bo'lganda shunga murojaat qiling.

Manzil kerak bo'lganda

Ba'zan boshqa funksiya ishni bajaradi. Aytaylik, metrikalar jamoasi shu yordamchini yetkazadi:

example.go
func Calibrate(p *int, offset int) {
	*p -= offset
}

U *int qabul qiladi, shuning uchun unga elementning manzilini berasiz:

example.go
for i := range samples {
	Calibrate(&samples[i], offset)
}

&samples[i] tub massivdagi i elementiga ishora qiladi. Yordamchi o'sha pointer orqali yozadi, va slice o'zgarishni ko'radi.

Kontentni tahrirlash va slicening o'zini qayta belgilash

Slice qiymati allaqachon o'z tub massiviga havolani olib yuradi, shuning uchun funksiya oddiy []int orqali elementlarni tahrirlashi mumkin. Buning uchun *[]int kerak emas. *[]intga faqat funksiya slice header'ining o'zini qayta belgilaganda, masalan uni append bilan kengaytirganda murojaat qiling.

>_ Exercise

Onlayn do'kon mijoz bitta buyurtmada bitta mahsulotdan qancha sotib olishi mumkinligini cheklaydi. Savatchangiz har bir mahsulot uchun sonini ushlab turadi. Hech qanday son shu buyurtma chegarasidan oshmasligi kerak. Ikkala funksiyani yozing:

Signaturalar

example.go
func Limit(qty *int, max int)
func LimitAll(quantities []int, max int)

Talablar

  • Limit *int qabul qiladi va uni faqat maxdan oshsa maxgacha qisqartiradi
  • LimitAll quantitiesdagi har bir element uchun bir marta Limitni chaqiradi, joyida o'zgartirib, qaytish qiymatisiz

Qochish kerak bo'lgan tuzoq

for _, q := range quantities { Limit(&q, max) } slice elementining emas, sikl o'zgaruvchisining manzilini oladi. Buning o'rniga indeks bo'yicha aylaning.

Stuck? Reveal a hint to help you.

Hints (0/5)

Key Takeaway

Key Takeaway:

range sizga har bir elementning nusxasini beradi, shuning uchun slicani o'zgartirish uchun uning haqiqiy elementiga samples[i] orqali indeks bilan yetib borasiz.

NEXT UP

Pointer to Struct