Rust এ এরর হ্যান্ডলিং
রাস্টে, এরর হ্যান্ডলিং দুটি প্রধান পদ্ধতির মাধ্যমে করা হয়:
Resultটাইপ (for recoverable errors)panic!ম্যাক্রো (for unrecoverable errors)
রাস্টে এরর হ্যান্ডলিং খুবই শক্তিশালী, এবং এর মাধ্যমে আমরা খুব সুরক্ষিতভাবে এবং প্রেডিক্টেবলভাবে ত্রুটিগুলিকে ধরতে এবং মোকাবেলা করতে পারি।
Result টাইপ
রাস্টের Result টাইপ সবচেয়ে সাধারণ এবং প্রায়ই ব্যবহৃত হয় ত্রুটি হ্যান্ডলিংয়ের জন্য, যেখানে এর দুটি ভ্যালু থাকে:
Ok(T): এটি একটি সফল ফলাফল (success result) প্রতিনিধিত্ব করে, যেখানেTহচ্ছে রিটার্ন ভ্যালু।Err(E): এটি একটি ত্রুটি (error result) প্রতিনিধিত্ব করে, যেখানেEহচ্ছে ত্রুটির ধরন।
Result এর সিঙ্কট্যাক্স:
enum Result<T, E> {
Ok(T),
Err(E),
}Result ব্যবহার:
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("Cannot divide by zero")) // ত্রুটি রিটার্ন
} else {
Ok(a / b) // সফল ফলাফল রিটার্ন
}
}
fn main() {
let result = divide(10, 0);
match result {
Ok(value) => println!("Result: {}", value),
Err(e) => println!("Error: {}", e),
}
}ব্যাখ্যা:
- এখানে
divideফাংশনটি দুইটি ইন্টিজার প্যারামিটার নেয় এবং একটিResultরিটার্ন করে। - যদি
b == 0হয়, তাহলেErrরিটার্ন করবে, অন্যথায়Okরিটার্ন করবে। matchব্লকটি ব্যবহার করে, আমরাResultএর মান পরীক্ষা করি এবং তা অনুযায়ী সঠিক প্রক্রিয়া গ্রহণ করি।
panic! ম্যাক্রো (Unrecoverable Errors)
কিছু ত্রুটি (যেগুলি একে অপর থেকে পুনরুদ্ধার করা সম্ভব নয়) যখন ঘটে, তখন panic! ম্যাক্রো ব্যবহার করা হয়। এটি প্রোগ্রামকে থামিয়ে দেয় এবং একটি ত্রুটি বার্তা প্রদর্শন করে।
panic! এর সিঙ্কট্যাক্স:
panic!("Error message");উদাহরণ:
fn cause_panic() {
panic!("Something went wrong!");
}
fn main() {
cause_panic(); // এই লাইনে প্রোগ্রাম প্যানিক করবে
}ব্যাখ্যা:
cause_panicফাংশনটিpanic!ম্যাক্রো কল করে, যা প্রোগ্রামটি থামিয়ে দেয় এবং এরর মেসেজ প্রদর্শন করে।
নোট: panic! শুধুমাত্র গুরুতর ত্রুটির জন্য ব্যবহৃত হয়, যেখানে প্রোগ্রামটি পুনরায় চালু করা সম্ভব নয় (যেমন, অ্যারে ইনডেক্স আউট অব বাউন্ড, অপর্যাপ্ত মেমোরি ইত্যাদি)। সাধারনত, আপনার প্রোগ্রামে panic! এড়িয়ে চলতে চেষ্টা করা উচিত এবং Result ব্যবহারের মাধ্যমে এরর হ্যান্ডলিং করা উচিত।
Option টাইপ
রাস্টে, কখনও কখনও এমন কিছু মান হতে পারে যা উপলব্ধ না থাকতে পারে (যেমন, None), এবং এজন্য Option টাইপ ব্যবহৃত হয়। Option দুইটি ভ্যালু থাকতে পারে:
Some(T): যেখানেTহল ভ্যালু।None: যখন কোনো ভ্যালু উপস্থিত না থাকে।
Option সাধারণত ত্রুটি হ্যান্ডলিংয়ের জন্য ব্যবহার করা হয় যখন ভ্যালু হতে পারে না, তবে তা কখনও ত্রুটি হিসেবে গণ্য হয় না।
Option এর সিঙ্কট্যাক্স:
enum Option<T> {
Some(T),
None,
}Option ব্যবহার:
fn find_item(items: Vec<i32>, index: usize) -> Option<i32> {
if index < items.len() {
Some(items[index])
} else {
None
}
}
fn main() {
let numbers = vec![1, 2, 3, 4];
let result = find_item(numbers, 5);
match result {
Some(value) => println!("Found: {}", value),
None => println!("Item not found"),
}
}ব্যাখ্যা:
find_itemফাংশনটিOptionটাইপ রিটার্ন করে। যদি ইনডেক্স বৈধ হয়, তাহলেSome(value)রিটার্ন করে, আর যদি ইনডেক্স আউট অফ রেঞ্জ হয়, তাহলেNoneরিটার্ন করে।
৫. unwrap এবং expect
রাস্টে, আপনি Result বা Option টাইপের ভ্যালুর উপর কাজ করতে পারেন unwrap এবং expect ম্যাক্রো ব্যবহার করে। এগুলি, যদি Err বা None পাওয়া যায়, তাহলে প্রোগ্রামটি panic করবে এবং এরর মেসেজ দেখাবে।
unwrap এর উদাহরণ:
fn main() {
let result: Result<i32, String> = Ok(10);
let value = result.unwrap(); // যদি Ok হয়, তাহলে এর ভ্যালু পাবো, অন্যথায় প্যানিক হবে
println!("{}", value);
}expect এর উদাহরণ:
fn main() {
let result: Result<i32, String> = Err(String::from("Something went wrong"));
let value = result.expect("Failed to get the result"); // প্যানিক হবে এবং কাস্টম মেসেজ দেখাবে
println!("{}", value);
}unwrap এবং expect ব্যবহারের ক্ষেত্রে, আপনি নিশ্চিত হন না যে, ফাংশনটি সফল হবে বা না, সেক্ষেত্রে এগুলি ব্যবহার করা এড়ানো উচিত। সেগুলি সাধারণত ডেভেলপমেন্ট বা টেস্টিংয়ের সময় ব্যবহার করা হয়।
Error Propagation (ত্রুটি প্রপাগেশন)
রাস্টে, ত্রুটি প্রপাগেশন একটি সাধারণ ধারণা যেখানে আপনি একটি ত্রুটি অন্য ফাংশনে পাঠাতে পারেন। এটি ? অপারেটর ব্যবহার করে করা হয়। এটি একটি Result বা Option টাইপে প্রাপ্ত ত্রুটিকে সরাসরি উপরের স্তরে পাঠিয়ে দেয়।
উদাহরণ:
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("Cannot divide by zero"))
} else {
Ok(a / b)
}
}
fn main() -> Result<(), String> {
let result = divide(10, 0)?;
println!("Result: {}", result);
Ok(())
}ব্যাখ্যা:
- এখানে
?অপারেটরdivideফাংশনের ফলাফল চেক করে এবং যদি কোনোErrপাওয়া যায়, তাহলে তা প্রপাগেট হয়েmainফাংশনে চলে যায়।
সারাংশ:
রাস্টে Error Handling খুবই শক্তিশালী এবং সুরক্ষিতভাবে করা যায়। এর জন্য সাধারণত Result টাইপ ব্যবহৃত হয়, যা পুনরুদ্ধারযোগ্য ত্রুটির জন্য উপযোগী। অন্যদিকে, panic! ম্যাক্রো ব্যবহার করা হয় অপ্রত্যাশিত এবং গুরুতর ত্রুটির জন্য। Option টাইপও ব্যবহৃত হয় যখন কোন ভ্যালু অনুপস্থিত হতে পারে। ত্রুটি প্রপাগেশন, unwrap এবং expect এর মাধ্যমে ত্রুটি মোকাবেলার প্রক্রিয়া আরও সহজ করা হয়, তবে এগুলি ব্যবহারে সাবধানতা অবলম্বন করা উচিত।
Recoverable Errors (পুনরুদ্ধারযোগ্য ত্রুটি)
পুনরুদ্ধারযোগ্য ত্রুটি (Recoverable errors) হল এমন ত্রুটি যেগুলি প্রোগ্রাম চলাকালীন সময়ে পুনরুদ্ধার করা যেতে পারে বা তাদের সমাধান করা যেতে পারে। এই ধরনের ত্রুটি সাধারণত ব্যবহারকারীর ইনপুটের কারণে বা বাহ্যিক উৎস থেকে আসে, যেমন ফাইল খোলার চেষ্টা করা, ইন্টারনেট কানেকশনের সমস্যা ইত্যাদি।
Recoverable Errors Handling in Rust
রাস্টে, এই ধরনের ত্রুটিগুলি Result টাইপ ব্যবহার করে পরিচালনা করা হয়। Result হল একটি enum যা দুটি ভ্যারিয়েবল ধারণ করে:
Ok(T)- সফল রিটার্ন ভ্যালু (অর্থাৎ কোনো ত্রুটি হয়নি)Err(E)- ত্রুটি ভ্যালু (যেখানেEত্রুটির বিস্তারিত)
উদাহরণ:
use std::fs::File;
use std::io::Read;
fn read_file() -> Result<String, std::io::Error> {
let mut file = File::open("example.txt")?; // ফাইল খোলার চেষ্টা করা
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
fn main() {
match read_file() {
Ok(contents) => println!("File contents: {}", contents),
Err(e) => println!("Error reading file: {}", e),
}
}এখানে, File::open এবং read_to_string দুটি কার্যকলাপ recoverable errors ফেলে, যেগুলিকে Result enum ব্যবহার করে পুনরুদ্ধার করা যায়। যদি ফাইল খোলার সময় কোনো সমস্যা হয়, তাহলে Err ফেরত আসবে, আর অন্যথায় Ok ফেরত আসবে।
Unrecoverable Errors (অপুনরুদ্ধারযোগ্য ত্রুটি)
অপুনরুদ্ধারযোগ্য ত্রুটি (Unrecoverable errors) হল এমন ত্রুটি যেগুলি সাধারণত প্রোগ্রামের চলমান অবস্থার জন্য অপ্রত্যাশিত এবং একে পুনরুদ্ধার করা সম্ভব নয়। এগুলি প্রোগ্রাম চলাকালীন সময়ে এমন পরিস্থিতিতে ঘটে যেখানে প্রোগ্রামকে থামিয়ে দেওয়া অথবা অন্যভাবে হ্যান্ডেল করা ছাড়া কোনো বিকল্প নেই।
Unrecoverable Errors Handling in Rust
রাস্টে, অপুনরুদ্ধারযোগ্য ত্রুটি panic! ম্যাক্রো ব্যবহার করে হ্যান্ডেল করা হয়। এই ম্যাক্রোটি ত্রুটি ঘটানোর সময় প্রোগ্রামটি থামিয়ে দেয় এবং প্রোগ্রামকে ক্র্যাশ করে।
উদাহরণ:
fn divide(x: i32, y: i32) -> i32 {
if y == 0 {
panic!("Attempted to divide by zero!"); // অপুনরুদ্ধারযোগ্য ত্রুটি
}
x / y
}
fn main() {
let result = divide(10, 0); // এখানে panicked হবে
println!("Result: {}", result);
}এখানে, divide ফাংশনটি y এর মান 0 হলে panic! ম্যাক্রো ব্যবহার করে প্রোগ্রামটি থামিয়ে দেয়। এই ধরনের ত্রুটি সাধারণত সেই ক্ষেত্রে ঘটে যেখানে একে পুনরুদ্ধার করা সম্ভব নয় এবং প্রোগ্রামকে থামানো ছাড়া অন্য কোনো উপায় থাকে না।
Recoverable এবং Unrecoverable Errors এর মধ্যে পার্থক্য
| পার্থক্য | Recoverable Errors (পুনরুদ্ধারযোগ্য) | Unrecoverable Errors (অপুনরুদ্ধারযোগ্য) |
|---|---|---|
| উদাহরণ | ফাইল না পাওয়া, ইন্টারনেট কানেকশন সমস্যার কারণে ডাটা পাঠাতে না পারা | 0 দিয়ে ভাগ করার চেষ্টা, ইনডেক্স আউট অফ রেঞ্জ |
| হ্যান্ডলিং | Result enum ব্যবহার করে, match বা unwrap দিয়ে হ্যান্ডেল করা হয় | panic! ম্যাক্রো ব্যবহার করে, প্রোগ্রাম বন্ধ হয়ে যায় |
| পুনরুদ্ধারযোগ্যতা | পুনরুদ্ধার করা সম্ভব | পুনরুদ্ধার করা সম্ভব নয় |
| ফলস্বরূপ | প্রোগ্রাম চালু থাকে, তবে ফলস্বরূপে ত্রুটি হতে পারে | প্রোগ্রাম থেমে যায় এবং ত্রুটির বার্তা দেখানো হয় |
সারাংশ
রাস্টে ত্রুটির দুটি প্রধান ধরন রয়েছে:
- Recoverable errors (পুনরুদ্ধারযোগ্য ত্রুটি): এগুলি
Resultenum ব্যবহার করে হ্যান্ডল করা হয় এবং প্রোগ্রাম চলতে থাকে। উদাহরণস্বরূপ, ফাইল না খোলা বা ইন্টারনেট কানেকশন সমস্যা। - Unrecoverable errors (অপুনরুদ্ধারযোগ্য ত্রুটি): এগুলি
panic!ম্যাক্রো ব্যবহার করে হ্যান্ডল করা হয়, যেখানে প্রোগ্রাম থেমে যায়। উদাহরণস্বরূপ, 0 দিয়ে ভাগ করা বা আউট অফ বাউন্ড ইনডেক্স অ্যাক্সেস করা।
রাস্টের এই দুটি ত্রুটি হ্যান্ডলিং মডেল প্রোগ্রামারের জন্য শক্তিশালী এবং নিরাপদ প্রোগ্রামিংয়ের সুবিধা প্রদান করে।
Result
রাস্টে Result একটি খুব গুরুত্বপূর্ণ এবং শক্তিশালী টিউপল (tuple) ধরনের ডেটা, যা মূলত ফাংশন বা অপারেশনের সফল বা ব্যর্থ ফলাফল ফিরিয়ে দেয়। Result দুটি ভ্যালু ধারণ করে:
- Ok(T): অপারেশন সফল হলে, যেখানে
Tহল সফল ফলাফল। - Err(E): অপারেশন ব্যর্থ হলে, যেখানে
Eহল ত্রুটির তথ্য।
Result টাইপটি প্রধানত ত্রুটি হ্যান্ডলিং (error handling) এর জন্য ব্যবহৃত হয় এবং এটি Rust-এর মূল ফিচারগুলির মধ্যে একটি।
উদাহরণ:
ধরা যাক, আমরা একটি সংখ্যাকে আরেকটি সংখ্যায় ভাগ করতে চাই এবং ফলস্বরূপ Result টাইপ ব্যবহার করে ত্রুটি এবং সফল ফলাফল হ্যান্ডল করতে চাই।
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("Cannot divide by zero"))
} else {
Ok(a / b)
}
}
fn main() {
let result = divide(10, 2);
match result {
Ok(value) => println!("Result is {}", value),
Err(e) => println!("Error: {}", e),
}
}এখানে, divide ফাংশন দুটি ভ্যালু ফেরত দেয়:
- যদি দ্বিতীয় প্যারামিটার শূন্য না হয়, তাহলে
Ok(a / b)ফেরত দেয়, যেখানেa / bহল সফল ফলাফল। - যদি দ্বিতীয় প্যারামিটার শূন্য হয়, তাহলে
Errফেরত দেয়, যেখানে ত্রুটির বার্তা হিসেবে"Cannot divide by zero"দেওয়া হয়।
match স্টেটমেন্টের মাধ্যমে Result এর দুটি ভ্যালু Ok এবং Err হ্যান্ডল করা হয়।
Result এর কিছু প্রধান বৈশিষ্ট্য:
unwrap(): এটিOkভ্যালু রিটার্ন করলে সেই ভ্যালু দেয়, তবে যদিErrহয়, তাহলে প্রোগ্রামটি প্যানিক করে।map(): এটি সফল হলে, অপারেশনটি প্রয়োগ করে এবং নতুনResultতৈরি করে।and_then(): এটি চেইনিং অপারেশন করতে ব্যবহৃত হয়, যাতে একাধিকResultএর উপর কাজ করা যায়।
Option
রাস্টে Option হল একটি ডেটা টাইপ যা দুইটি ভ্যালু ধারণ করতে পারে:
- Some(T): এটি
Tধরনের মান ধারণ করে, যা প্রমাণ করে যে কিছু মান উপস্থিত রয়েছে। - None: এটি বোঝায় যে কোনো মান উপস্থিত নেই।
Option মূলত null বা undefined এর প্রতিস্থাপন হিসেবে ব্যবহৃত হয়, যাতে কোডে ভুল বা নিরাপত্তাহীন null রেফারেন্স না আসে।
উদাহরণ:
ধরা যাক, আমরা একটি ফাংশন লিখেছি যা একটি নাম গ্রহণ করে এবং তার প্রথম অক্ষর ফিরিয়ে দেয়, কিন্তু যদি নাম শূন্য হয়, তাহলে None ফেরত দিবে।
fn first_char(name: &str) -> Option<char> {
if name.is_empty() {
None
} else {
Some(name.chars().next().unwrap())
}
}
fn main() {
let name = "Alice";
match first_char(name) {
Some(c) => println!("First character is {}", c),
None => println!("No character found"),
}
}এখানে, first_char ফাংশন একটি Option<char> ফেরত দেয়:
- যদি নামটি শূন্য না হয়, তাহলে
Some(c)দিয়ে প্রথম অক্ষর রিটার্ন করবে। - যদি নামটি শূন্য হয়, তাহলে
Noneরিটার্ন করবে।
match স্টেটমেন্টের মাধ্যমে Option এর Some এবং None ভ্যালু হ্যান্ডল করা হয়।
Option এর কিছু প্রধান বৈশিষ্ট্য:
unwrap(): এটিSomeভ্যালু রিটার্ন করলে তার ভ্যালু দেয়, তবে যদিNoneহয়, প্রোগ্রামটি প্যানিক করে।map(): এটি সফল হলে, অপারেশনটি প্রয়োগ করে এবং নতুনOptionতৈরি করে।and_then(): এটি চেইনিং অপারেশন করতে ব্যবহৃত হয়, যাতে একাধিকOptionএর উপর কাজ করা যায়।
Result এবং Option এর মধ্যে পার্থক্য
- Result সাধারণত ত্রুটি পরিচালনার জন্য ব্যবহৃত হয়, যেখানে কিছু অপারেশন সফল না হলে একটি ত্রুটি বার্তা ফেরত দেওয়া হয়।
Resultত্রুটি এবং সফল ফলাফলের মধ্যে পার্থক্য নির্ধারণ করে। - Option সাধারণত যখন কোনো মান হতে পারে না বা শূন্য হতে পারে, তখন ব্যবহৃত হয়। এটি শুধু মানের অস্তিত্ব চেক করে, তবে কোনো ত্রুটি বার্তা থাকে না।
উদাহরণ:
Resultব্যবহার করা হবে যদি আপনি একটি অপারেশন বা ফাংশনের মধ্যে ত্রুটি বা ব্যর্থতা শিকার করতে চান, যেমন ফাইল খোলার সময় ত্রুটি, অথবা নেটওয়ার্ক রিকোয়েস্ট ব্যর্থ হলে।Optionব্যবহার করা হবে যদি আপনি নিশ্চিত না হন যে কোনো মান রয়েছে কি না, যেমন একটি অ্যারে থেকে একটি উপাদান খোঁজার সময়।
সারাংশ
Result এবং Option রাস্টের দুটি অত্যন্ত গুরুত্বপূর্ণ ডেটা টাইপ, যা ত্রুটি এবং মানের অস্তিত্ব সুরক্ষিতভাবে পরিচালনা করতে সহায়তা করে। Result ব্যবহৃত হয় ত্রুটি হ্যান্ডলিংয়ের জন্য, যেখানে আপনি সফল বা ব্যর্থ অপারেশন থেকে তথ্য ফেরত পান, এবং Option ব্যবহৃত হয় যখন কোনো মান থাকতে পারে বা না থাকতে পারে, সেই পরিস্থিতিতে কোড লেখার জন্য।
panic! ম্যাক্রো
রাস্টে panic! একটি ম্যাক্রো যা প্রোগ্রামের চলাকালীন অবস্থা যদি এমন কিছু ঘটে যা সিস্টেমে unrecoverable (অগ্রাহ্যযোগ্য) ত্রুটি তৈরি করে, তাহলে এটি প্রোগ্রামটি থামিয়ে দেয়। panic! সাধারণত তখন ব্যবহৃত হয় যখন কোনো অবস্থা এমন থাকে যে, প্রোগ্রাম চলতে না পারার মতো সমস্যা হয়ে থাকে এবং তারপরে এর কাজ চলতে থাকা আর নিরাপদ থাকে না। এটি প্রোগ্রামের একেবারে শেষের দিকে চলে যায় এবং রানটাইমের শেষে একটি ত্রুটি বার্তা দেখিয়ে প্রোগ্রামটি থামিয়ে দেয়।
panic! ব্যবহারের উদাহরণ:
fn main() {
let number = -5;
if number < 0 {
panic!("Negative numbers are not allowed: {}", number);
}
}এখানে, number যদি ০ এর কম হয়, তবে panic! ম্যাক্রোটি চলবে এবং প্রোগ্রামটি ত্রুটি বার্তা সহ থেমে যাবে।
আউটপুট:
thread 'main' panicked at 'Negative numbers are not allowed: -5', src/main.rs:3:9panic! ম্যাক্রোটি একটি run-time error ঘটায়, যা সিস্টেমের জন্য একটি অপরিহার্য অবস্থা হতে পারে। যখন প্রোগ্রামে কোনো অগ্রাহ্যযোগ্য ত্রুটি ঘটবে, তখন panic! স্বয়ংক্রিয়ভাবে থ্রো হয় এবং প্রোগ্রাম থেমে যায়।
Unrecoverable Errors (অগ্রাহ্যযোগ্য ত্রুটি)
রাস্টে unrecoverable errors সেই ত্রুটিগুলি যা শুধুমাত্র panic! ম্যাক্রোর মাধ্যমে মোকাবেলা করা হয়। এগুলি সাধারণত এমন অবস্থায় ঘটে, যেখানে কোনো অবস্থা পুনরুদ্ধার করা সম্ভব নয় এবং প্রোগ্রাম চালিয়ে যাওয়া নিরাপদ নয়। একে fatal errors বা critical errors বলা হয়।
Unrecoverable Errors এর উদাহরণ:
- Invalid input: যদি কোনো ফাংশনে অবৈধ ইনপুট আসে এবং সেই ইনপুট থেকে কোড চলতে না পারে।
- File system error: কোনো ফাইল সিস্টেমের জন্য সমস্যা, যেমন ফাইল খুঁজে না পাওয়া বা ফাইল মুছে যাওয়া।
- Index out of bounds: যখন অ্যারে বা ভেক্টরের মধ্যে এমন একটি ইনডেক্স অ্যাক্সেস করা হয়, যা সেখানে উপস্থিত নেই।
Unrecoverable Error Example (Array Index Out of Bounds):
fn main() {
let arr = [1, 2, 3];
let index = 10;
let element = arr[index]; // This will panic because the index is out of bounds
println!("The element is: {}", element);
}এখানে, arr[10] অ্যাক্সেস করতে গেলে panic! ম্যাক্রোটি ট্রিগার হবে, কারণ অ্যারের সাইজ কেবল ৩টি উপাদান (index 0, 1, 2) ধারণ করে। এটি রানটাইমে একটি অগ্রাহ্যযোগ্য ত্রুটি ঘটায়।
আউটপুট:
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 10', src/main.rs:4:13এই ধরনের ত্রুটিতে প্রোগ্রাম আর চালানো সম্ভব হয় না, তাই রাস্ট panic! ম্যাক্রো ব্যবহারের মাধ্যমে প্রোগ্রামটিকে থামিয়ে দেয়।
panic! এবং Unrecoverable Errors এর ব্যবহারের জায়গা
panic!ব্যবহৃত হয় তখন, যখন কোনো ত্রুটি ঘটে যা প্রোগ্রামটির নিরাপত্তা বা কার্যকারিতা বিপর্যস্ত করে এবং পুনরুদ্ধার করা সম্ভব নয়।- এই ধরনের ত্রুটির ক্ষেত্রে সিস্টেম স্থিতিশীলতা বজায় রাখতে প্রোগ্রামটিকে বন্ধ করা হয়।
কিন্তু মনে রাখতে হবে, panic! ম্যাক্রো ব্যবহারের ফলে প্রোগ্রাম থেমে যায় এবং কোনো ধরনের পুনরুদ্ধার সম্ভব হয় না। তাই এটি ব্যবহৃত হওয়ার সময় সতর্ক থাকতে হয়।
Recoverable Errors (পুনরুদ্ধারযোগ্য ত্রুটি) এবং Result
যখন একটি ত্রুটি পুনরুদ্ধারযোগ্য হয়, অর্থাৎ আপনি সেই ত্রুটিকে ঠিক করতে বা প্রোগ্রাম চালিয়ে যেতে চান, তখন Result টাইপ ব্যবহৃত হয়। এটি সাধারণত I/O operations, file handling, এবং network calls এর ক্ষেত্রে ব্যবহৃত হয়। এটি একটি enum যা দুটি ভ্যালু ধারণ করতে পারে: Ok(T) এবং Err(E)। Result ব্যবহৃত হলে প্রোগ্রামটি বন্ধ হবে না, বরং ত্রুটির সাথে মোকাবিলা করে চলতে পারে।
সারাংশ
রাস্টের panic! ম্যাক্রোটি ব্যবহার করা হয় unrecoverable errors মোকাবিলা করতে, যখন প্রোগ্রামটি আর নিরাপদভাবে চলতে পারে না। এটি সাধারণত ত্রুটির সম্মুখীন হলে প্রোগ্রাম বন্ধ করে দেয় এবং রানটাইম ত্রুটি বার্তা দেখায়। এই ব্যবস্থায়, আপনি প্রোগ্রামটির নিরাপত্তা এবং সঠিকতার জন্য নিশ্চিত করতে পারেন যে, কোনো পরিস্থিতিতে সিস্টেমে ভুল বা অবৈধ কাজ চলতে না পারে।
Rust-এ Custom Errors তৈরি করা খুবই গুরুত্বপূর্ণ, কারণ এটি আপনাকে আপনার প্রোগ্রামে স্পষ্ট এবং বোধগম্য ত্রুটি বার্তা প্রদান করতে সাহায্য করে। Rust-এর ত্রুটি ব্যবস্থাপনা ব্যবস্থা Result এবং Option টাইপ ব্যবহার করে, যেখানে ত্রুটির জন্য সাধারণত Err ভ্যারিয়েবল ব্যবহৃত হয়। আপনি যখন একটি Custom Error তৈরি করবেন, তখন আপনি আপনার নিজের ত্রুটি টাইপ তৈরি করতে পারবেন এবং সেটিকে সুন্দরভাবে প্রিন্ট করতে পারবেন।
Custom Error তৈরি করার জন্য Steps
১. Custom Error টাইপ তৈরি করা
প্রথমে, আপনি একটি নতুন enum বা struct তৈরি করবেন যা ত্রুটির জন্য বিভিন্ন ধরন (variants) ধারণ করবে।
২. Error Trait ইমপ্লিমেন্ট করা
Rust-এর std::error::Error ট্রেইটটি ব্যবহার করা হয়। আপনার কাস্টম ত্রুটির ধরন Error ট্রেইটটি ইমপ্লিমেন্ট করতে পারে, যাতে আপনার ত্রুটির জন্য একটি description() এবং cause() মেথড ব্যবহার করা যায়।
৩. Debug এবং Display Trait ইমপ্লিমেন্ট করা
যেহেতু কাস্টম ত্রুটির জন্য Debug এবং Display ট্রেইট ইমপ্লিমেন্ট করা যেতে পারে, তাই আপনি ত্রুটি বার্তা সুন্দরভাবে আউটপুট করতে পারবেন।
উদাহরণ: Custom Error তৈরি করা
১. Custom Error টাইপ তৈরি করা
আমরা একটি MyError নামক কাস্টম ত্রুটি তৈরি করব।
use std::fmt;
#[derive(Debug)]
enum MyError {
NotFound,
InvalidInput,
}এখানে, MyError নামক একটি enum তৈরি করা হয়েছে যেটি দুটি ভ্যারিয়েন্ট ধারণ করে: NotFound এবং InvalidInput।
২. Error ট্রেইট ইমপ্লিমেন্ট করা
আমরা std::error::Error ট্রেইটটি আমাদের কাস্টম ত্রুটির জন্য ইমপ্লিমেন্ট করব, যাতে ত্রুটির বর্ণনা এবং কারণ (cause) প্রদান করা যায়।
use std::fmt;
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MyError::NotFound => write!(f, "Error: Not Found"),
MyError::InvalidInput => write!(f, "Error: Invalid Input"),
}
}
}
impl std::error::Error for MyError {}এখানে, fmt::Display ট্রেইটটি ইমপ্লিমেন্ট করার মাধ্যমে MyError এ to_string() মেথড প্রদান করা হয়েছে, যা ত্রুটির বর্ণনা করবে। std::error::Error ট্রেইটটি ব্যবহার করে MyError কাস্টম ত্রুটির জন্য description() মেথডও সরবরাহ করা হয়েছে।
৩. ব্যবহার উদাহরণ
এখন, কাস্টম ত্রুটি ব্যবহার করা যাক। আমরা একটি ফাংশন তৈরি করব যা একটি ত্রুটি ফেরত দেয়।
fn check_input(input: i32) -> Result<(), MyError> {
if input < 0 {
Err(MyError::InvalidInput)
} else if input == 0 {
Err(MyError::NotFound)
} else {
Ok(())
}
}
fn main() {
match check_input(-1) {
Ok(_) => println!("Valid input!"),
Err(e) => println!("Error occurred: {}", e),
}
}এখানে, check_input ফাংশনটি একটি Result ফেরত দেয়, যা Ok হলে কোনো ত্রুটি নেই এবং Err হলে কাস্টম ত্রুটি ফেরত দেয়। main ফাংশনে আমরা এই ত্রুটিকে ম্যাচ করে আউটপুট প্রিন্ট করি।
আউটপুট:
Error occurred: Error: Invalid InputCustom Error-এ আরও বেশি Flexibility
আপনি চাইলে আরও অনেক কাস্টম ত্রুটি ধরন তৈরি করতে পারেন। উদাহরণস্বরূপ, আপনি struct ব্যবহার করে আরও বিস্তারিত ত্রুটি বার্তা প্রদান করতে পারেন।
use std::fmt;
#[derive(Debug)]
struct MyError {
details: String,
}
impl MyError {
fn new(msg: &str) -> MyError {
MyError {
details: msg.to_string(),
}
}
}
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Error: {}", self.details)
}
}
impl std::error::Error for MyError {}
fn cause_error() -> Result<(), MyError> {
Err(MyError::new("Something went wrong!"))
}
fn main() {
match cause_error() {
Ok(_) => println!("No error occurred"),
Err(e) => println!("Error: {}", e),
}
}এখানে, MyError নামক একটি স্ট্রাকচার ব্যবহার করে কাস্টম ত্রুটি তৈরি করা হয়েছে, যেখানে একটি বিস্তারিত ত্রুটি বার্তা থাকে।
সারাংশ
Rust-এ Custom Errors তৈরি করার মাধ্যমে আপনি ত্রুটি ব্যবস্থাপনায় উন্নত এবং বোধগম্য কাস্টমাইজেশন পেতে পারেন। আপনি enum বা struct ব্যবহার করে কাস্টম ত্রুটি টাইপ তৈরি করতে পারেন এবং Error, Debug, ও Display ট্রেইট ইমপ্লিমেন্ট করে সেগুলিকে সুন্দরভাবে প্রিন্ট করতে পারেন। এটি আপনার কোডে আরও পরিষ্কার এবং অর্থবোধক ত্রুটি বার্তা প্রদান করতে সাহায্য করে।
Read more