ماڈیول اسباق (2/5)
محاوراتی غلطی کو سنبھالنا
Go میں ہینڈلنگ کی خرابی واضح ہے: کوئی استثنا نہیں، کوئی کوشش/کیچ نہیں۔ ہر فنکشن جو ناکام ہو سکتا ہے error کو اس کی آخری قدر کے طور پر واپس کرتا ہے، اور کال کرنے والا فیصلہ کرتا ہے۔ یہ باب ایک مضبوط طریقے سے غلطیاں پیدا کرنے، پھیلانے اور ان کا معائنہ کرنے کے لیے محاوراتی نمونوں کو جمع کرتا ہے۔
سنہری اصول
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("config %s: %w", path, err)
}چار اصول:
errorآخری واپسی ہے۔if err != nilکے ساتھ **فوری طور پر چیک کریں۔- پروپیگنڈے سے پہلے **سیاق و سباق شامل کریں (
fmt.Errorf+%wکے ساتھ)۔ - کبھی نظر انداز نہ کریں غلطی: یا تو اسے ہینڈل کریں، اسے لاگ کریں، یا اسے واپس کریں۔
_ = file.Close() // EXPLICITLY ignored (you know what you're doing)سینٹینل کی غلطیاں
ایک سینٹینل ایرر ایک برآمد شدہ عالمی متغیر ہے var ErrXxx = errors.New("...") جس کا کال کرنے والا موازنہ کر سکتا ہے:
package store
var ErrNotFound = errors.New("not found")
func Get(key string) (string, error) {
if !exists(key) {
return "", ErrNotFound
}
// ...
}کال کرنے والا errors.Is (NOT ==) کا استعمال کرتا ہے، جو لفافے کی زنجیر پر چلتا ہے:
v, err := store.Get(k)
if errors.Is(err, store.ErrNotFound) {
// handle 404
}معیاری مثالیں: io.EOF، sql.ErrNoRows، os.ErrNotExist۔
حسب ضرورت ٹائپ شدہ غلطیاں
سٹرکچرڈ ڈیٹا لے جانے کے لیے (HTTP کوڈ، غلط فیلڈ، وغیرہ)، ایک قسم کی وضاحت کریں:
type ValidationError struct {
Field string
Msg string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Msg)
}کال کرنے والا errors.As کا استعمال کرتا ہے تاکہ زنجیر کے ساتھ محفوظ طریقے سے نیچے جا سکے:
var ve *ValidationError
if errors.As(err, &ve) {
fmt.Println("invalid field:", ve.Field)
}errors.As اس وقت تک Unwrap() سلسلہ چلتا ہے جب تک کہ اس میں پاس کردہ پوائنٹر کو تفویض کردہ غلطی نہ ملے۔
%w کے ساتھ لپیٹنا
fmt.Errorf کے ساتھ %w فعل ایک خرابی پیدا کرتا ہے جو اصل کو ** لپیٹتا ہے**، اسے errors.Is/errors.As کے لئے محفوظ رکھتا ہے:
if err := db.Query(); err != nil {
return fmt.Errorf("load users: %w", err)
}%w کے بغیر (%v یا %s کا استعمال کرتے ہوئے) آپ کو ایک بھرپور سٹرنگ ملتی ہے لیکن زنجیر کھو دیتے ہیں: کال کرنے والا مزید مخصوص غلطیوں کو نہیں پہچان سکتا۔
%w کے لیے اصول:
- فی
fmt.Errorfکال صرف ایک (ملٹی ریپ کی ضرورت ہےerrors.Join)۔ - استدلال ایک
errorہونا چاہیے، تار نہیں۔ - سیاق و سباق شامل کریں، اصل پیغام کی نقل نہ بنائیں۔
// bad: duplicates
return fmt.Errorf("error: %w", err) // "error: file not found"
// good: useful context
return fmt.Errorf("load config %s: %w", path, err)errors.Join متعدد خرابیوں کے لیے
Go 1.20 کے بعد سے، errors.Join(errs...) ایک سے زیادہ خرابیوں کو یکجا کرتا ہے جو ان سب کو errors.Is/As کے ذریعہ قابل شناخت رکھتا ہے:
var errs []error
for _, item := range items {
if err := process(item); err != nil {
errs = append(errs, fmt.Errorf("item %s: %w", item.ID, err))
}
}
if len(errs) > 0 {
return errors.Join(errs...)
}کب استعمال کریں panic
متوقع غلطیوں کے لیے کبھی نہیں۔ صرف تین صورتوں میں:
- ناقابل بازیافت بگ: ایک ایسی جگہ پر خلاف ورزی کی گئی جو "نہیں ہو سکتی" (
panic("unreachable"))۔ - اسٹینڈ اسٹون پروگرام کے
init()/main()میں ناکام آغاز (نازک کنفیگریشن غائب → فیل فاسٹ)۔ - لائبریری API جو واضح طور پر اس کی دستاویز کرتا ہے: جیسے،
regexp.MustCompile(اگر پیٹرن غلط ہے تو گھبراہٹ - قابل قبول کیونکہ پیٹرن تعمیر وقت کا مستقل ہے)۔
باقی سب کچھ error ہے۔ ** پھیلانے کے لیے ** panic کو شارٹ کٹ کے طور پر استعمال نہ کریں: یہ کمپوزیشن کو توڑتا ہے، defer Close() کو چھوڑ دیتا ہے، اور کال کرنے والے کو مغلوب کر دیتا ہے۔
مشقیں
Wrappa l'errore di os.ReadFile con fmt.Errorf usando il verbo %w e aggiungendo il contesto 'config:' (con il path)۔
3 کوششوں کے بعد حل دستیاب ہے۔
Usa errors.Is per verificare se err nella catena di wrap corrisponde alla sentinella ErrNotFound e stampa 'manca!' tal caso میں.
3 کوششوں کے بعد حل دستیاب ہے۔
Quando è idiomatico usare panic in una libreria Go?
func F(x int) {
// ??? panic(...)
}