এর

এরর মধ্যে Go

2টি অনুশীলনী

এরর সম্পর্কে

এরর ইন্টারফেস

Go-তে এরর হ্যান্ডলিং এক্সেপশনের মাধ্যমে করা হয় না। বরং, এরর হলো এমন টাইপের সাধারণ মান, যেগুলো বিল্ট-ইন error ইন্টারফেস ইমপ্লিমেন্ট করে। error ইন্টারফেসটি খুবই ছোট। এতে মাত্র একটি মেথড Error() আছে, যা এরর মেসেজটি একটি স্ট্রিং হিসেবে রিটার্ন করে।

type error interface {
  Error() string
}

আপনি যখন এমন একটি ফাংশন ডিফাইন করেন, যার এক্সিকিউশনের সময় কোনো এরর ঘটতে পারে এবং সেটি কলার পর্যন্ত পৌঁছানো প্রয়োজন, তখন রিটার্ন টাইপের একটি হিসেবে error অন্তর্ভুক্ত করতে হবে। ফাংশনের একাধিক রিটার্ন ভ্যালু থাকলে, প্রচলিত রীতি অনুযায়ী error সবসময় সবার শেষেরটি হয়।

func DoSomething() (int, error) {
  // ...
}

একটি সাধারণ এরর তৈরি ও রিটার্ন করা

এরর ইন্টারফেসটি সবসময় আপনাকে নিজে ইমপ্লিমেন্ট করতে হবে না। একটি সাধারণ এরর তৈরি করতে আপনি errors.New() ফাংশনটি ব্যবহার করতে পারেন, যা স্ট্যান্ডার্ড লাইব্রেরির errors প্যাকেজের অংশ। আপনাকে শুধু এরর মেসেজটি একটি স্ট্রিং হিসেবে পাস করতে হবে, আর আপনার মেসেজটি ধারণ করে এবং error ইন্টারফেস ইমপ্লিমেন্ট করে এমন একটি মান তৈরি করার দায়িত্ব errors.New() নেবে।

ফাংশন যদি একটি এরর রিটার্ন করে, তবে বাকি সব রিটার্ন প্যারামিটারের জন্য জিরো ভ্যালু রিটার্ন করা ভালো অভ্যাস:

func DoSomething() (SomeStruct, int, error) {
  // ...
  return SomeStruct{}, 0, errors.New("failed to calculate result")
}
Caution

কোনো এরর থাকলে সব ফাংশনই বাকি রিটার্ন ভ্যালুগুলোর জন্য জিরো ভ্যালু রিটার্ন করে, এমন ধরে নেওয়া আপনার উচিত নয়। এরর রিটার্ন হলে বাকি রিটার্ন ভ্যালুগুলোর কোনোটিই ব্যবহার করা নিরাপদ নয়, এটাই ধরে নেওয়া সর্বোত্তম অভ্যাস।

উদাহরণ হিসেবে ভাবুন, একটি ফাংশন একটি ফাইল থেকে পড়ার চেষ্টা করছিল এবং সেটি আধা-ভরা একটি বাইট স্লাইস ও একটি এরর রিটার্ন করল। এরর হয়েছিল বলে রিটার্ন করা বাইট স্লাইসটি সবসময় খালি, এমন ধরে নিয়ে আপনি যদি আপনার কোডে সেটি আবার ব্যবহার করেন, তাহলে সূক্ষ্ম বাগে পড়তে পারেন।

একমাত্র ব্যতিক্রম হলো সেই সব ক্ষেত্রে, যেখানে ফাংশনের ডকুমেন্টেশনে স্পষ্টভাবে বলা থাকে যে এরর হলেও বাকি রিটার্ন ভ্যালুগুলোর অর্থ আছে। একটি উদাহরণের জন্য [বাফারে Write-এর ডকুমেন্টেশন][buffer-write] দেখুন।

আপনার দেওয়া এরর মেসেজটি যতটা সম্ভব নির্দিষ্ট কি না তা নিশ্চিত করুন, কারণ ডিফল্টভাবে এররে কোনো স্ট্যাক ট্রেস থাকে না। প্রচলিত রীতি অনুযায়ী, এরর মেসেজটি ছোট হাতের অক্ষর দিয়ে শুরু হওয়া উচিত এবং এর শেষে পূর্ণচ্ছেদ থাকা উচিত নয়।

আপনি যদি এমন একটি এরর একাধিক জায়গায় ব্যবহার করতে চান (অথবা আপনার প্যাকেজের ব্যবহারকারীর কাছে এররটি পৌঁছে দিতে চান), তাহলে errors.New সরাসরি ব্যবহার না করে এররের জন্য একটি ভ্যারিয়েবল ডিক্লেয়ার করা উচিত। প্রচলিত রীতি অনুযায়ী, ভ্যারিয়েবলের নাম Err বা err দিয়ে শুরু হওয়া উচিত (এটি এক্সপোর্টেড কি না, তার উপর নির্ভর করে)। এই এরর ভ্যারিয়েবলগুলোকে প্রায়ই সেন্টিনেল এরর বলা হয়।

import "errors"

var ErrNotFound = errors.New("resource was not found")

func DoSomething() error {
  // ...
  return ErrNotFound
}

ফাংশন এক্সিকিউশনের সময় কোনো এরর হয়নি বোঝাতে এররের জন্য nil রিটার্ন করুন:

func Foo() (int, error) {
  return 10, nil
}

এরর মেসেজে ভ্যারিয়েবল অন্তর্ভুক্ত করা

কিছু ভ্যারিয়েবল থেকে আরও জটিল একটি এরর মেসেজ তৈরি করতে হলে আপনি স্ট্রিং ফরম্যাটিং ব্যবহার করতে পারেন। এই উদ্দেশ্যে Go-তে একটি বিশেষ fmt.Errorf ফাংশন আছে। এটি এরর মেসেজ স্ট্রিংটি তৈরি করে এবং একটি এরর রিটার্ন করে।

input := 123
action := "UPDATE"

err := fmt.Errorf("invalid input %d for action %s", input, action)
err.Error()
// => "invalid input 123 for action UPDATE"

এরর চেক করা

আপনি যদি এমন একটি ফাংশন কল করেন যা একটি এরর রিটার্ন করে, তাহলে এরর ভ্যালুটি সাধারণত err নামের একটি ভ্যারিয়েবলে রাখা হয়। ফাংশনের প্রকৃত ফলাফল ব্যবহার করার আগে, কোনো এরর হয়নি কি না তা চেক করতে হবে। এররকে nil-এর সাথে তুলনা করতে আমরা == এবং != ব্যবহার করতে পারি, আর err যদি nil না হয় তাহলে বুঝতে হবে একটি এরর হয়েছে।

আপনার কোডের "হ্যাপি পাথ" নেস্টেড হওয়া এড়াতে, এরর কেসগুলো আগে হ্যান্ডেল করা উচিত, সাধারণত আর্লি রিটার্নের মাধ্যমে। আরও বিস্তারিত জানতে Mat Ryer-এর এই বিখ্যাত নিবন্ধটি দেখুন।

// Do this:
func myFunc() error {
  file, err := os.Open("./users.csv")
  if err != nil {
    return err
  }
  // do something with file
}

// Not this:
func myFunc() error {
  file, err := os.Open("./users.csv")
  if err != nil {
    // handle err
  } else {
    // do something with file
  }
}

// Also not this:
func myFunc() error {
  file, err := os.Open("./users.csv")
  if err == nil {
    // do something with file
  }
  // handle err
}

বেশিরভাগ ক্ষেত্রেই উপরের প্রথম উদাহরণে দেখানো মতো এররটি ফাংশন স্ট্যাক বরাবর উপরে রিটার্ন করা হয়। এরর হ্যান্ডেল করার আরেকটি উপায় হতে পারে এটি লগ করা এবং অন্য কোনো কাজ চালিয়ে যাওয়া। এরর হয় রিটার্ন করা, নয়তো লগ করা ভালো অভ্যাস; দুটোই কখনো নয়।

Go-তে বেশিরভাগ ফাংশনই রিটার্ন ভ্যালুর একটি হিসেবে একটি এরর রাখে, তাই Go কোডে আপনি সর্বত্র if err != nil প্যাটার্নটি দেখতে পাবেন ও ব্যবহার করবেন।

কাস্টম এরর টাইপ

আপনার এররে যদি শুধু এরর মেসেজ স্ট্রিংয়ের চেয়ে বেশি তথ্য রাখতে চান, তাহলে আপনি একটি কাস্টম এরর টাইপ তৈরি করতে পারেন। আগেই বলা হয়েছে, Go-তে যা-ই error ইন্টারফেসটি ইমপ্লিমেন্ট করে (অর্থাৎ যার একটি Error() string মেথড আছে), সেটিই এরর হিসেবে কাজ করতে পারে।

সাধারণত কাস্টম এরর টাইপ তৈরি করতে একটি স্ট্রাক্ট ব্যবহার করা হয়। প্রচলিত রীতি অনুযায়ী, কাস্টম এরর টাইপের নাম Error দিয়ে শেষ হওয়া উচিত। এছাড়া, Error() string মেথডটি পয়েন্টার রিসিভার দিয়ে সেট আপ করা ভালো; এর কারণ জানতে এই Stackoverflow কমেন্টটি দেখুন। মনে রাখবেন, এর মানে হলো আপনাকে আপনার কাস্টম এররের একটি পয়েন্টার রিটার্ন করতে হবে, নইলে সেটি error হিসেবে গণ্য হবে না, কারণ নন-পয়েন্টার মানটি Error() string মেথড প্রদান করে না।

type MyCustomError struct {
  message string
  details string
}

func (e *MyCustomError) Error() string {
  return fmt.Sprintf("%s, details: %s", e.message, e.details)
}

func someFunction() error {
  // ...
  return &MyCustomError{
    message: "...",
    details: "...",
  }
}
GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি নতুন একটি উইন্ডো বা ট্যাবে খুলবে

এরর শিখুন

অনুশীলন লক করা আছে

এরর অনুশীলন করতে আরও 4টি অনুশীলনী আনলক করুন