Идиоматическая обработка ошибок Голанга
Я создал базовую структуру репозитория для автономного и встроенного использования (например, с 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
}
Ответы
Ответ 1
Идиоматическим способом было бы вернуть ошибку с соответствующим значением типа, т.е.
func (list ...interface{}) (v int46, err error) {}
... и затем проверить err!= nil, где вызывается эти функции.
В конечном итоге использование panic() приведет к обработке ошибок, подобной исключению, и коду с кодовым номером (если вы считаете ошибку, подлежащую восстановлению).
Идиоматическая обработка ошибок является многословной в Go, но меньше, чем эмуляция исключений (что принципиально не является "Go way" ).
Ответ 2
Не паникуйте, это не путь. Вместо этого сделайте что-то вроде этого -
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")
Создайте все, что имеет смысл для вашего кода.