Представьте, что Вы открыли коннект к БД, получили курсор и делаете, как обычно:
defer c.Close()
Но в этом коде есть нюанс. Очень часто, Close() возвращает ошибку. В таком случае, мне не ясно, что с ней делать. С одной стороны есть замечательный оператор defer, который мне очень нравится, с другой стороны, мне не хочется делать, как написано тут, ибо такой способ обработки ошибок мешает читать код:
func DoStuff() (s string, err error) {
// note the named responses needed for the defer to return an error
myFile, err := os.Open("filename")
if err != nil {
return "", errors.New("Couldn't open file: " + err.Error())
}
defer func() {
if cerr := myFile.Close(); cerr != nil && err == nil {
err = cerr
}
}()
// Do stuff
return "someString", nil
}
Я также нашёл вот такую реализацию, но она оказалась нерабочей:
func safeClose(c io.Closer, err *error) {
if cerr := c.Close(); cerr != nil && *err == nil {
*err = cerr
}
}
func WriteFile(filename string, data []byte) (err error) {
f, err := os.Create(filename)
if err != nil {
return err
}
defer safeClose(f, &err)
_, err = f.Write(data)
return err
}
Я переписал её:
func safeClose(err *error) {
*err = errors.New("123")
}
func f() error {
var err error
defer safeClose(&err)
return err
}
func main() {
e := f()
fmt.Println(e)
}
Оказалось, что я получаю:
<nil>
Вопросы:
Можно ли исправить мой пример?
Как поступать в такой истуации: с или без
defer?
cerr? И какой смысл использовать такое огромное замыкание? Оно же плохо читается – hedgehogues Jun 27 '19 at 16:36