Golang惯用错误处理

时间:2014-01-21 17:47:11

标签: go

我为独立和嵌入式使用创建了一个“基础”存储库结构(例如,使用CustomerRepository),以避免不断检查错误,并为Gorp(数据库工具包)创建抽象,并创建API更喜欢我的意思。

我检查了这个基本结构中的错误,如果发现了一个就发生了恐慌,好像我确实存在一个错误,然后它表示一个dev错误,代码可能也会出现恐慌,因为在数据获取之前应该看到验证等到存储库。

我发现了这个问题Go Error Handling Techniques,但它没有涵盖像我一样在基础结构中包装错误而只是恐慌。

我做了什么惯用Go?

package repositories

import (
    "github.com/coopernurse/gorp"
)

type Repository struct {
    Gorp gorp.SqlExecutor
}

func (r *Repository) GetById(i interface{}, id int) interface{} {
    obj, err := r.Gorp.Get(i, id)
    if err != nil {
        panic(err)
    }
    return obj
}

func (r *Repository) Get(holder interface{}, query string, args ...interface{}) interface{} {
    if err := Gorp.SelectOne(holder, query, args); err != nil {
        panic(err)
    }
}

func (r *Repository) Select(i interface{}, query string, args ...interface{}) {
    if _, err := Gorp.Select(holder, query, args); err != nil {
        panic(err)
    }
}

func (r *Repository) Insert(list ...interface{}) {
    if err := r.Gorp.Insert(list...); err != nil {
        panic(err)
    }
}

func (r *Repository) Update(list ...interface{}) int64 {
    count, err := r.Gorp.Update(list...)
    if err != nil {
        panic(err)
    }
    return count
}

func (r *Repository) Delete(list ...interface{}) int64 {
    count, err := r.Gorp.Delete(list...)
    if err != nil {
        panic(err)
    }
    return count
}

2 个答案:

答案 0 :(得分:10)

惯用的方法是返回带有相关类型值的错误,即

func (list ...interface{}) (v int46, err error) {}

...然后检查err!= nil,调用这些函数。

最终使用panic()将导致类似Exception的错误处理和更多的样板代码(如果您认为错误是可恢复的)。

习惯性错误处理在Go中很详细,但不如模拟异常(基本上不是“Go way”)。

答案 1 :(得分:10)

不要惊慌,这不是Go方式。相反,做这样的事情 -

func (r *Repository) GetById(i interface{}, id int) (interface{}, error) {
    obj, err := r.Gorp.Get(i, id)
    if err != nil {
        return nil, err
    }
    return obj, nil
}

然后只需处理调用者的错误。我从上面的评论中看到你在Martini处理程序中使用这些函数,所以你会做这样的事情 -

func MyHandler(parameters) (int, string) {
    obj, err := repository.GetById(something, id)
    if err == repository.ErrNotFound {
        return http.StatusNotFound, fmt.Sprintf("could not find by id: %d", id)
    }
    if err != nil {
        return http.StatusInternalError, err.Error()
    }
    return http.StatusOk, fmt.Printf("obj: %v", obj)
}

这更像是Go方式。确保r.Gorp.Get确实返回您在包中声明的特定错误。

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

尽可能多地创建代码。