GoDasturchi
Don't Return Interfaces

Don't Return Interfaces

Interfeys qaytarmang

"Accept Interfaces, Return Structs" darslarida ko'rgan umumiy qoidaning davomi: aksariyat holatlarda funksiyalar aniq struct qaytarishi kerak, interfeys emas. Buning ustiga, interfeys qaytarish nozik xatoga ham olib kelishi mumkin.

example.go
package main

import "fmt"

type MyError struct{ msg string }

func (e *MyError) Error() string { return e.msg }

// XAVFLI: har doim *MyError (pointer) qaytaradi
func doSomethingBad(fail bool) *MyError {
	if fail {
		return &MyError{msg: "ish bajarilmadi"}
	}
	return nil
}

func wrapper(fail bool) error {
	// *MyError -> error'ga aylantirilganda, nil bo'lsa ham "bo'sh interfeys" BO'LMAYDI!
	return doSomethingBad(fail)
}

func main() {
	err := wrapper(false)
	fmt.Println(err == nil) // kutilgan: true, lekin...
}

Bu — Go'dagi mashhur "nil interfeys tuzog'i". doSomethingBad(false) nil pointer qaytaradi, lekin uni error interfeysiga aylantirganda, natija interfeys ichida **"tur: *MyError, qiymat: nil" ma'lumotini saqlaydi — bu esa haqiqiy `nil`ga teng emas! Shuning uchun funksiya to'g'ridan-to'g'ri konkret struct/pointer qaytarishi, `error` kabi interfeysga faqat haqiqatan xato bo'lganda** aylantirilishi kerak (masalan if err != nil { return err }; return nil naqshi bilan, to'g'ridan-to'g'ri emas).

>_ Exercise

Nil interfeys tuzog'idan qochib, to'g'ri naqsh bilan yozing.

  • validate(age int) *ValidationError yozing (aniq pointer qaytaradi, error emas)
  • safeValidate(age int) error yozing: agar validate natijasi nil bo'lsa aniq nil, aks holda uni qaytarsin

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Nil pointer'ni to'g'ridan-to'g'ri interfeys sifatida qaytarish "nil interfeys tuzog'i"ga olib keladi — buning o'rniga if err != nil { return err }; return nil naqshini ishlating.

NEXT UP

Avoid Interface Pollution

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Don't Return Interfaces

Interfeys qaytarmang

"Accept Interfaces, Return Structs" darslarida ko'rgan umumiy qoidaning davomi: aksariyat holatlarda funksiyalar aniq struct qaytarishi kerak, interfeys emas. Buning ustiga, interfeys qaytarish nozik xatoga ham olib kelishi mumkin.

example.go
package main

import "fmt"

type MyError struct{ msg string }

func (e *MyError) Error() string { return e.msg }

// XAVFLI: har doim *MyError (pointer) qaytaradi
func doSomethingBad(fail bool) *MyError {
	if fail {
		return &MyError{msg: "ish bajarilmadi"}
	}
	return nil
}

func wrapper(fail bool) error {
	// *MyError -> error'ga aylantirilganda, nil bo'lsa ham "bo'sh interfeys" BO'LMAYDI!
	return doSomethingBad(fail)
}

func main() {
	err := wrapper(false)
	fmt.Println(err == nil) // kutilgan: true, lekin...
}

Bu — Go'dagi mashhur "nil interfeys tuzog'i". doSomethingBad(false) nil pointer qaytaradi, lekin uni error interfeysiga aylantirganda, natija interfeys ichida **"tur: *MyError, qiymat: nil" ma'lumotini saqlaydi — bu esa haqiqiy `nil`ga teng emas! Shuning uchun funksiya to'g'ridan-to'g'ri konkret struct/pointer qaytarishi, `error` kabi interfeysga faqat haqiqatan xato bo'lganda** aylantirilishi kerak (masalan if err != nil { return err }; return nil naqshi bilan, to'g'ridan-to'g'ri emas).

>_ Exercise

Nil interfeys tuzog'idan qochib, to'g'ri naqsh bilan yozing.

  • validate(age int) *ValidationError yozing (aniq pointer qaytaradi, error emas)
  • safeValidate(age int) error yozing: agar validate natijasi nil bo'lsa aniq nil, aks holda uni qaytarsin

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Nil pointer'ni to'g'ridan-to'g'ri interfeys sifatida qaytarish "nil interfeys tuzog'i"ga olib keladi — buning o'rniga if err != nil { return err }; return nil naqshini ishlating.

NEXT UP

Avoid Interface Pollution