A Cairo hibakezelési technikákat kínál a problémák orvoslására és a hibák kezelésére, ami lehetővé teszi, hogy a kód zökkenőmentesen fusson a végrehajtás során.
A Cairóban kétféle hiba létezik:
panic-kel - ezek a hibák azonnal leállítják a programot.Result-tal - ezek a hibák futásidőben kezelhetők.panic
A Cairóban váratlan problémák merülhetnek fel a program végrehajtása közben, amelyek „panic” nevű futásidejű hibákat okoznak.
Ez leállítja a program végrehajtását, ami hasznos, ha a folytatásnak nem lenne semmi értelme.
A panic véletlenül is bekövetkezhet, olyan műveletek hatására, amelyek panicet okoznak a kódban (például egy tömb határain túli elérése), vagy szándékosan, a panic függvény meghívásával.
fn main() {
let data = array![1, 2];
if true {
panic(data);
}
println!("This line will not be reached.");
}
Ha lefuttatod ezt a példát, a következő jelenik meg a konzolon:
Run panicked with [1, 2, ].
Létezik egy speciális makró is, a panic!, amely lehetővé teszi, hogy egy ByteArray-t használj hibaüzenetként.
panic!("The error for the panic! Error message is not limited to 31 characters anymore");
assert! makróAz assert! makró hasznos eszköz arra, hogy meghatározott feltételeket érvényesíts a kódodban.
Ha az assert!-ban szereplő feltétel false értékre értékelődik ki, a program egy ByteArray hibaüzenettel panicel.
Ezt gyakran használják feltevések ellenőrzésére fejlesztés közben, és annak biztosítására, hogy az értékek megfeleljenek bizonyos feltételeknek.
Például:
fn main() {
let x = 5;
assert!(x > 0, "x must be greater than zero");
}
Ha x nem nagyobb nullánál, a program a "x must be greater than zero" üzenettel panicel.
Az assert! segít az invariánsok és előfeltételek ellenőrzésében anélkül, hogy kézzel kellene hibakezelő kódot írnod.
nopanic jelölésA Cairo nopanic jelölése azt jelzi, hogy egy függvény soha nem fog panicelni.
fn function_never_panic() -> felt252 nopanic {
108
}
Egy nopanic függvényt csak olyan függvényből lehet meghívni, amely szintén nopanic jelöléssel van ellátva.
panic_with attribútumA Cairo panic_with attribútuma megjelöl egy olyan függvényt, amely Option vagy Result típust ad vissza, és létrehoz egy wrappert a megjelölt függvényedhez, amely panicel, ha a függvény Option::None vagy Result::Err értéket ad vissza.
#[panic_with('value is 0', wrap_not_zero)]
fn check_not_zero(value: u128) -> Option<u128> {
if value == 0 {
Option::None
} else {
Option::Some(value)
}
}
fn main() {
check_not_zero(0); // -> returns Option::None
wrap_not_zero(0); // -> panics with 'value is 0'
}
Result
A Result enum kecsesen kezeli a hibákat: visszajelzést ad ahelyett, hogy összeomlana vagy nem definiált viselkedést produkálna.
enum Result<T, E> {
Ok: T,
Err: E,
}
Nézzünk egy példát arra, hogyan használhatjuk ezt az enumot a nullával való osztás kezelésére:
fn divide(a: u32, b: u32) -> Result<u32, ByteArray> {
if b == 0 {
return Result::Err("Error: Division by zero"); // Return an error if division by zero is attempted
}
Result::Ok(a / b)
}
fn main() {
// Test with division by zero
match divide(10, 0) {
Result::Ok(result) => println!("Division successful: {}", result),
Result::Err(e) => println!("{}", e),
}
}
? operátorA ? operátor a tömör és implicit hibakezelést szolgálja, és hagyja, hogy a hívó függvény foglalkozzon a felmerülő hibákkal.
Amikor a ? operátort Result vagy Option típuson használod, a következőt teszi:
Result::Ok(x) vagy Option::Some(x), akkor közvetlenül visszaadja a belső x értéket.Result::Err(e) vagy Option::None, akkor továbbadja a hibát vagy a None-t úgy, hogy azonnal visszatér a függvényből.fn parse_u8(s: felt252) -> Result<u8, felt252> {
match s.try_into() {
Option::Some(value) => Result::Ok(value),
Option::None => Result::Err('Invalid integer'),
}
}
fn do_something_with_parse_u8(input: felt252) -> Result<u8, felt252> {
let input_to_u8: u8 = parse_u8(input)?;
// DO SOMETHING
let res = input_to_u8 - 1;
Result::Ok(res)
}
fn main() {
let number: felt252 = 258;
match do_something_with_parse_u8(number) {
Result::Ok(value) => println!("Result: {}", value),
Result::Err(e) => println!("Error: {}", e),
}
}