Go / Алдаа зохицуулах

Алдаа зохицуулах

Go хэл алдааг зохицуулах өвөрмөц аргатай. Exception throw хийдэг Python эсвэл JavaScript-с ялгаатай нь Go-д алдааг утга болгон буцаадаг. Энэ нь эхлэхэд хачирхалтай санагдаж болох боловч кодыг хамаагүй тодорхой, урьдчилан тооцоолж болохуйц болгодог.

error тип

Go-д error бол суурилагдсан interface юм:

go
type error interface {
    Error() string
}

Функц алдааг хоёр дахь буцах утга болгон буцаадаг хэв маяг бий:

go
package main

import (
    "errors"
    "fmt"
)

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("тэгд хуваах боломжгүй")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 2)
    if err != nil {
        fmt.Println("Алдаа:", err)
        return
    }
    fmt.Printf("10 / 2 = %.1f\n", result)

    _, err = divide(5, 0)
    if err != nil {
        fmt.Println("Алдаа:", err)
    }
}

Алдаа гараагүй бол nil буцаадаг. nil гэдэг нь "алдаа байхгүй" гэсэн утгатай.

if err != nil хэв маяг

Go-д алдааг шалгах хамгийн түгээмэл хэв маяг:

go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // Мөрийг тоо руу хөрвүүлэх
    num, err := strconv.Atoi("123")
    if err != nil {
        fmt.Println("Хөрвүүлэлт амжилтгүй:", err)
        return
    }
    fmt.Println("Тоо:", num)

    // Буруу оролт
    _, err = strconv.Atoi("абвгд")
    if err != nil {
        fmt.Println("Хөрвүүлэлт амжилтгүй:", err)
    }
}

strconv.Atoi нь мөрийг int болгон хөрвүүлдэг. Амжилтгүй бол алдаа буцаана.

Олон алдаа зохицуулах

Нэг функц дотор олон алдаа шалгах шаардлагатай байдаг:

go
package main

import (
    "errors"
    "fmt"
)

func getUser(id int) (string, error) {
    if id <= 0 {
        return "", errors.New("id тэгээс их байх ёстой")
    }
    if id > 100 {
        return "", errors.New("хэрэглэгч олдсонгүй")
    }
    return fmt.Sprintf("Хэрэглэгч_%d", id), nil
}

func getUserEmail(name string) (string, error) {
    if name == "" {
        return "", errors.New("нэр хоосон байна")
    }
    return name + "@example.com", nil
}

func main() {
    user, err := getUser(42)
    if err != nil {
        fmt.Println("Алдаа:", err)
        return
    }

    email, err := getUserEmail(user)
    if err != nil {
        fmt.Println("Алдаа:", err)
        return
    }

    fmt.Printf("Хэрэглэгч: %s, И-мэйл: %s\n", user, email)
}

Алдаа гарсан даруй return хийх нь Go-ийн стандарт хэв маяг юм.

fmt.Errorf — алдааг формат болгох

Алдааны мессежид нэмэлт мэдээлэл оруулахдаа fmt.Errorf ашигладаг:

go
package main

import "fmt"

func openFile(name string) error {
    // Жишээ болгон үргэлж алдаа буцааж байна
    return fmt.Errorf("файл нээхэд алдаа гарлаа: %s олдсонгүй", name)
}

func main() {
    err := openFile("data.txt")
    if err != nil {
        fmt.Println(err)
    }
}

%w verb ашиглан алдааг "ороож" болно — ингэснээр алдааны гинж (error wrapping) үүснэ. Go 1.13-с дэмжигддэг.

Алдаа шалгах зөв заншил

Алдааг хэзээ ч үл тоомсорлох ёсгүй. Дараах хэв маяг буруу:

go
// БУРУУ — алдааг орхиж байна
result, _ := divide(10, 0)
fmt.Println(result)

// ЗӨВ — алдааг шалгаж байна
result, err := divide(10, 0)
if err != nil {
    fmt.Println("Алдаа гарлаа:", err)
    return
}
fmt.Println(result)

_ ашиглан алдааг орхих нь цаашид debug хийхэд маш хэцүү байдлыг бий болгодог.

Дараагийн хичээлд:

Суурилагдсан алдааны тип хангалтгүй үед өөрийн алдааны тип үүсгэх аргыг сурна. Ингэснээр алдааны мэдээллийг илүү нарийн дамжуулах боломжтой болно.