Возможно, вы можете использовать два разных подхода; либо defer
, либо, как вы предложили, с помощью другой функции.
Отсрочка будет работать так:
// All of these must be defined before we call defer.
var err error
var progressResponse string
var errorMessage string
defer func() {
// Since the deferred function will be called even if
// the function has completed successfully, we need to
// check that there actually has been an error before we
// create the error response.
if err == nil {
return
}
pr := progressRes{
Type: progressResponse,
Message: err.Error(),
MessageType: errorMessage,
Progress: 100,
}
go response(ws, pr.json())
}()
nodes, err := model.AllNodes()
if err != nil {
// The deferred function will automatically be called here.
return
}
links, err := model.AllLinks()
if err != nil {
// And in every other place where the function returns.
return
}
Проблема здесь в том, что могут быть некоторые подводные камни, связанные с изменением теней. Возьмите этот пример:
var err error
defer func() {
if err != nil {
handleError(err)
}
}()
if a, err := doSomething(); err != nil {
return
}
Вот подтверждение концепции на детской площадке .
Проблема здесь в том, что err
внутри предложения if
не совпадает с тем, что в верхней области видимости; если вы также объявляете a
в верхней области и используете одно присваивание =
вместо объявления :=
, то оно работает как ожидалось . Затенение переменных является распространенной ошибкой, особенно для начинающих; дальнейшее чтение .
Таким образом, подход, который я обычно использую и рекомендую, заключается в наличии другой функции. В любом случае вызывающей стороне нужен только один фактический аргумент возврата, поэтому он обычно не становится очень сложным.
func a() {
links, err := b()
if err != nil {
pr := progressRes{
Type: progressResponse,
Message: err.Error(),
MessageType: errorMessage,
Progress: 100,
}
go response(ws, pr.json())
return
}
}
func b() ([]Link, error) {
nodes, err := model.AllNodes()
if err != nil {
return nil, err
}
links, err := model.AllLinks()
if err != nil {
return nil, err
}
// you probably then do something with nodes and links?
return resolveLinks(nodes, links)
}