Search code examples
golabelgoto

Use Go goto label on Err


I want to use label to minimize err part like this:

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)
}

so i could have one place to put all the err handling in one place, but seems not working as

./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)

is there a way to use goto to make it work?


Solution

  • The reason why the compiler is complaining is defined in the Go spec:

    Executing the "goto" statement must not cause any variables to come into scope that were not already in scope at the point of the goto. For instance, this example:

      goto L  // BAD  
      v := 3
    L:
    

    is erroneous because the jump to label L skips the creation of v.

    So you'll need to restructure your code. If you want to keep using goto here (as opposed to, say, if-else statements), then you'll have to move all the declarations up.

    Note that you can split it like this:

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

    It should be OK to goto L here.