GoDasturchi
The new Builtin

The new Builtin

Yangi `new` o'rnatilgan funksiyasi

Konfiguratsiya struct'i ko'pincha ikkita holatni farqlashi kerak: chaqiruvchi ataylab nolga o'rnatgan maydon, va u umuman o'rnatmagan maydon. Oddiy int buni qila olmaydi, chunki 0 ikkalasini ham anglatishi mumkin. Pointer esa qila oladi: nil — "o'rnatilmagan", boshqa istalgan qiymat — haqiqiy tanlov.

example.go
type RetryConfig struct {
	MaxAttempts *int  // nil "standartdan foydalanish"ni bildiradi, "nol urinish" emas
	Backoff     *bool // nil "o'rnatilmagan"ni bildiradi, "false" emas
}

Shunday qilib, MaxAttemptsni standart bo'yicha 5ga o'rnatish uchun, sizga 5ga ishora qiluvchi *int kerak. Ochiq-oydin yechim kompilyatsiya bo'lmaydi:

example.go
cfg.MaxAttempts = &5 // kompilyatsiya xatosi: 5ning manzilini olib bo'lmaydi

& o'zgaruvchining manzilini oladi, 5 esa o'zgaruvchi emas, literal. Xo'sh, literalga pointerni qanday olasiz?

Eski yechim

Eski kod literalni bitta qatorli yordamchiga o'raydi, shunda unga ishora qiladigan o'zgaruvchi paydo bo'ladi:

example.go
func intPtr(v int) *int { return &v }
cfg.MaxAttempts = intPtr(5)

Literal v parametriga aylanadi, bu o'zgaruvchi, shuning uchun &v to'g'ri. Shuning uchun intPtr, strPtr, va boolPtr shunchalik ko'p loyihalarda uchraydi.

Go 1.26 usuli

Go 1.26 newga faqat tur emas, ifodani ham qabul qilish imkonini beradi. U joy ajratadi, qiymatni saqlaydi va pointerni qaytaradi:

example.go
cfg.MaxAttempts = new(5)      // 5ga ishora qiluvchi *int, yordamchisiz
fmt.Println(*cfg.MaxAttempts) // 5

Bundan buyon newga murojaat qiling. O'sha intPtr yordamchilari faqat til keyinchalik yopgan bo'shliqni chetlab o'tish uchun mavjud edi.

>_ Exercise

Configda pointer maydonlari bor, shuning uchun nil "chaqiruvchi buni hech qachon o'rnatmagan"ni bildiradi, va nolmas har qanday qiymat — ataylab qilingan tanlov. U yaratadigan Server esa oddiy qiymatlarni ushlab turadi, chunki server yaratilgandan keyin har bir sozlama ma'lum bo'ladi. newServerni tugating, u o'rnatilmagan Config maydonlarini standart qiymatga o'rnatsin, so'ng hal qilingan qiymatlarni ushlab turuvchi *Server qaytarsin.

Config maydonlari pointer, Server maydonlari esa oddiy qiymat bo'lgani uchun, ularni ko'chirayotganda har birini dereferentsiya qiling: *cfg.Port — pointer ishora qilayotgan int.

Talablar

  • Agar Port nil bo'lsa, uni 8080ga standart qiling
  • Agar EnableTLS nil bo'lsa, uni truega standart qiling
  • Chaqiruvchi allaqachon o'rnatgan har qanday maydonni o'zgarishsiz qoldiring
  • Har bir standart literalga ishora qilish uchun new()dan foydalaning, yordamchi funksiyalarsiz
  • Serverning Addrini uning tinglash manziliga, "localhost:<port>", hal qilingan portdan foydalanib o'rnating (fmt.Sprintf("localhost:%d", port) ishlaydi; %d int'ni formatlaydi)
  • Port, EnableTLS, va Addri hal qilingan qiymatlarni ushlab turadigan *Server qaytaring

Stuck? Reveal a hint to help you.

Hints (0/5)

Key Takeaway

Key Takeaway:

new(expr) bitta qadamda qiymat ajratadi va unga pointer qaytaradi, shuning uchun *T maydoni intPtr-uslubidagi yordamchi o'rniga to'g'ridan-to'g'ri literalni olishi mumkin.

NEXT UP

Value vs Pointer Receivers

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

The new Builtin

Yangi `new` o'rnatilgan funksiyasi

Konfiguratsiya struct'i ko'pincha ikkita holatni farqlashi kerak: chaqiruvchi ataylab nolga o'rnatgan maydon, va u umuman o'rnatmagan maydon. Oddiy int buni qila olmaydi, chunki 0 ikkalasini ham anglatishi mumkin. Pointer esa qila oladi: nil — "o'rnatilmagan", boshqa istalgan qiymat — haqiqiy tanlov.

example.go
type RetryConfig struct {
	MaxAttempts *int  // nil "standartdan foydalanish"ni bildiradi, "nol urinish" emas
	Backoff     *bool // nil "o'rnatilmagan"ni bildiradi, "false" emas
}

Shunday qilib, MaxAttemptsni standart bo'yicha 5ga o'rnatish uchun, sizga 5ga ishora qiluvchi *int kerak. Ochiq-oydin yechim kompilyatsiya bo'lmaydi:

example.go
cfg.MaxAttempts = &5 // kompilyatsiya xatosi: 5ning manzilini olib bo'lmaydi

& o'zgaruvchining manzilini oladi, 5 esa o'zgaruvchi emas, literal. Xo'sh, literalga pointerni qanday olasiz?

Eski yechim

Eski kod literalni bitta qatorli yordamchiga o'raydi, shunda unga ishora qiladigan o'zgaruvchi paydo bo'ladi:

example.go
func intPtr(v int) *int { return &v }
cfg.MaxAttempts = intPtr(5)

Literal v parametriga aylanadi, bu o'zgaruvchi, shuning uchun &v to'g'ri. Shuning uchun intPtr, strPtr, va boolPtr shunchalik ko'p loyihalarda uchraydi.

Go 1.26 usuli

Go 1.26 newga faqat tur emas, ifodani ham qabul qilish imkonini beradi. U joy ajratadi, qiymatni saqlaydi va pointerni qaytaradi:

example.go
cfg.MaxAttempts = new(5)      // 5ga ishora qiluvchi *int, yordamchisiz
fmt.Println(*cfg.MaxAttempts) // 5

Bundan buyon newga murojaat qiling. O'sha intPtr yordamchilari faqat til keyinchalik yopgan bo'shliqni chetlab o'tish uchun mavjud edi.

>_ Exercise

Configda pointer maydonlari bor, shuning uchun nil "chaqiruvchi buni hech qachon o'rnatmagan"ni bildiradi, va nolmas har qanday qiymat — ataylab qilingan tanlov. U yaratadigan Server esa oddiy qiymatlarni ushlab turadi, chunki server yaratilgandan keyin har bir sozlama ma'lum bo'ladi. newServerni tugating, u o'rnatilmagan Config maydonlarini standart qiymatga o'rnatsin, so'ng hal qilingan qiymatlarni ushlab turuvchi *Server qaytarsin.

Config maydonlari pointer, Server maydonlari esa oddiy qiymat bo'lgani uchun, ularni ko'chirayotganda har birini dereferentsiya qiling: *cfg.Port — pointer ishora qilayotgan int.

Talablar

  • Agar Port nil bo'lsa, uni 8080ga standart qiling
  • Agar EnableTLS nil bo'lsa, uni truega standart qiling
  • Chaqiruvchi allaqachon o'rnatgan har qanday maydonni o'zgarishsiz qoldiring
  • Har bir standart literalga ishora qilish uchun new()dan foydalaning, yordamchi funksiyalarsiz
  • Serverning Addrini uning tinglash manziliga, "localhost:<port>", hal qilingan portdan foydalanib o'rnating (fmt.Sprintf("localhost:%d", port) ishlaydi; %d int'ni formatlaydi)
  • Port, EnableTLS, va Addri hal qilingan qiymatlarni ushlab turadigan *Server qaytaring

Stuck? Reveal a hint to help you.

Hints (0/5)

Key Takeaway

Key Takeaway:

new(expr) bitta qadamda qiymat ajratadi va unga pointer qaytaradi, shuning uchun *T maydoni intPtr-uslubidagi yordamchi o'rniga to'g'ridan-to'g'ri literalni olishi mumkin.

NEXT UP

Value vs Pointer Receivers