Использовать метку Go goto при ошибке

#go #label #goto

#Вперед #метка #goto

Вопрос:

Я хочу использовать label для минимизации ошибок, подобных этой:

 package main
import (
    "fmt"
    consul "github.com/hashicorp/consul/api"
    "os"
)
func main(){
    client,err := consul.NewClient(consul.DefaultConfig())
    if err != nil {
        goto Err
    }
    agent := client.Agent()
    checkReg := agent.AgentCheckRegistration{
        ID:   "test-check",
        Name: "test-check",
        Notes: "some test check",
    }
    if err = agent.CheckRegister(checkReg); err !=nil{
        goto Err
    }
Err:
    fmt.Println(err)
    os.Exit(2)
}
 

таким образом, у меня могло бы быть одно место для размещения всей обработки ошибок в одном месте, но, похоже, не работает как

 ./agent.CheckRegister.go:10:8: goto Err jumps over declaration of checkReg at 
./agent.CheckRegister.go:13:19: agent.AgentCheckRegistration undefined (type *api.Agent has no field or method AgentCheckRegistration)
 

есть ли способ использовать goto, чтобы заставить его работать?

Комментарии:

1. Нет, ошибка объясняет, почему. Предварительно проясните все, используйте условные блоки или функцию, в которую вы можете вернуться раньше

2. @JimB хорошо, спасибо.

Ответ №1:

Причина, по которой компилятор жалуется, определена в спецификации Go:

Выполнение инструкции «goto» не должно приводить к попаданию в область видимости каких-либо переменных, которые еще не были в области видимости в момент перехода. Например, этот пример:

   goto L  // BAD  
  v := 3
L:
 

ошибочно, потому что переход к метке L пропускает создание v.

Поэтому вам нужно будет реструктурировать свой код. Если вы хотите продолжать использовать goto here (в отличие, скажем, if-else от statements ), вам придется переместить все объявления вверх.

Обратите внимание, что вы можете разделить его следующим образом:

    var v Type
   ...
L: ...
   v = FunctionThatReturnsType()
 

Здесь все должно быть в порядке goto L .