156

I was surprised to find that Go has a 'goto' statement. I've always been taught that 'goto' statements are a thing of the past and evil for it occludes the actual flow of a program, and that functions or methods are always a better way of controlling flow.

I must be missing something. Why did Google include it?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
harm
  • 10,045
  • 10
  • 36
  • 41
  • 10
    There are times where you really need a goto statement. Goto's are evil only when used indiscriminately. For example, if it is very difficult, if not impossible, to write a Finite state machine parser withou goto statements. – Ayush Jun 16 '12 at 16:02
  • 5
    It's not specific to Go, but for a good discussion on why languages retain the statement, and to see arguments against its use, check out [this post](http://stackoverflow.com/questions/46586/goto-still-considered-harmful). There are some good references linked in the question. Edit: [here's another](http://stackoverflow.com/questions/24451/goto-usage). – Cᴏʀʏ Jun 16 '12 at 16:05
  • 3
    To save the OP from grepping through the provided SO discussions, here's [the discussion on LKML](http://kerneltrap.org/node/553/2131) which pretty much sums it up why `goto` is useful in certain cases. Read after studying @Kissaki's answer. – kostix Jun 16 '12 at 18:17
  • 1
    Related: http://programmers.stackexchange.com/q/566/33478 (and see [my answer](http://programmers.stackexchange.com/a/133523/33478)). – Keith Thompson Dec 16 '14 at 23:45
  • Its useful implementing a continuation pattern, where you save off the stack then goto back to where you were when you want to resume. – Justin Dennahower Jan 12 '18 at 23:47
  • 3
    Just another thing to note. `Go` does not have advanced control flow structures like exception flows, so naturally you have to compensate for that with `goto`'s – Ben Dec 19 '19 at 10:04

3 Answers3

106

When we actually check the source code of the Go standard library, we can see where gotos are actually well applied.

For example, in the math/gamma.go file, the goto statement is used:

  for x < 0 {
    if x > -1e-09 {
      goto small
    }
    z = z / x
    x = x + 1
  }
  for x < 2 {
    if x < 1e-09 {
      goto small
    }
    z = z / x
    x = x + 1
  }

  if x == 2 {
    return z
  }

  x = x - 2
  p = (((((x*_gamP[0]+_gamP[1])*x+_gamP[2])*x+_gamP[3])*x+_gamP[4])*x+_gamP[5])*x + _gamP[6]
  q = ((((((x*_gamQ[0]+_gamQ[1])*x+_gamQ[2])*x+_gamQ[3])*x+_gamQ[4])*x+_gamQ[5])*x+_gamQ[6])*x + _gamQ[7]
  return z * p / q

small:
  if x == 0 {
    return Inf(1)
  }
  return z / ((1 + Euler*x) * x)
}

The goto in this case saves us from introducing another (boolean) variable used just for control-flow, checked for at the end. In this case, the goto statement makes the code actually better to read and easier follow (quite in contrary to the argument against goto you mentioned).

Also note, that the goto statement has a very specific use-case. The language specification on goto states that it may not jump over variables coming into scope (being declared), and it may not jump into other (code-)blocks.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Kissaki
  • 8,810
  • 5
  • 40
  • 42
  • 103
    In your example, why not just introduce a function `small(x,z)` to call instead? That way we don't have to think about what variables are accessible in the `small:` label. I suspect the reason is go still lacks certain types of inlining support in the compiler. – Thomas Ahle Jun 02 '13 at 12:11
  • 3
    @Thomas, I'm pretty sure it's because of the lack of inlining in many cases. The computationally intensive applications where function calls matter tend to contain a lot of math so it's fairly reasonable to use goto in the math package. – Henry Heikkinen Jul 10 '14 at 06:32
  • 2
    @ThomasAhle functions imply reuse, once you have a function you then have to think about callers when you change it. – Jesse Jul 10 '14 at 22:15
  • 8
    @Jessta: That's what we've got visibility and scope for, right? – Thomas Ahle Jul 11 '14 at 00:13
  • 8
    @ThomasAhle Go does not allow `goto` to point to a label after new variables have been introduced. [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.](https://golang.org/ref/spec#Goto_statements) – km6zla Sep 11 '14 at 17:50
  • 7
    @ogc-nick Sorry I wasn't clear, I meant the functions can be declared in the scope where they are needed, so they aren't visible to code that doesn't need them. I wasn't talking about goto's and scope. – Thomas Ahle Sep 11 '14 at 23:09
  • 5
    @MosheRevah The referenced code is not optimized for readability. It is optimized for raw performance, using a goto that spans 22 lines within a single function. (And Thomas Ahle's proposal is even more readable to my eye.) – joel.neely Jun 28 '16 at 11:14
  • 3
    @Jessta In addition to the preceding comment, I'd also offer that, unlike most commercial/industrial application code, there is essentially zero risk that a business owner will come along and revise the requirements for the gamma function. Having to make changes in the middle of unnecessarily complex flow control is one of the places where spaghetti goto code really bites the later developers, in my experience. – joel.neely Jun 28 '16 at 11:17
  • 2
    It may be worth mentioning that the code is a direct port of C code to go. Have a look at the comment at the top of the file. – Guido Flohr Aug 27 '20 at 16:28
  • This answer makes good sense considering that the question was about why Google _might_ have considered a `goto` statement useful. Asking why @thomas-ahle didn't introduce a function in the example seems like the XY problem in reverse. – Jacob Wan Jul 14 '21 at 00:02
  • That file you've pointed to actually explicitly describes why the goto is there, in a comment: "// The go code is a simplified version of the original C." This is likely the case for most uses of goto in the Go source code, although only because Go was self-hosted by taking its C implementation and applying a bunch of automatic translation tools. That is also a reasonable view on why Go kept the goto statement: it greatly simplifies the translation from C to Go. Or if you like, put more simply as well as more generally: Go has a very strong C heritage. – Marcel Besixdouze Jun 29 '23 at 19:56
41

Goto is a good idea when none of the built-in control features do quite what you want, and when you can express what you want with a goto. (It's a shame in these cases in some languages when you don't have a goto. You end up abusing some control feature, using Boolean flags, or using other solutions worse than goto.)

If some other control feature (used in a reasonably obvious way) can do what you want, you should use it in preference to goto. If not, be bold and use goto!

Finally it's worth noting that Go's goto has some restrictions designed to avoid some obscure bugs. See these restrictions in the specification.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sonia
  • 27,135
  • 8
  • 52
  • 54
15

Goto statements has received a lot of discredit since the era of Spaghetti code in the 60s and 70s. Back then there was very poor to none software development methodology. However Goto are not natively evil but can of course be misused and abused by lazy or unskilled programmers. Many problems with abused Gotos can be solved with development processes such as team code reviews.

goto are jumps in the same technical manner as continue, break and return. One could argue that these are statements are evil in the same manner but they are not.

Why the Go team has included Gotos are probably because of the fact that it is a common flow control primitive. Additionally they hopefully concluded that the scope of Go excludes making an idiot-safe language not possible to abuse.

Gustav
  • 2,902
  • 1
  • 25
  • 31
  • 2
    `continue`, `break`, and `return` are very different in one key particular: they specify only "leave the enclosing scope". They not only encourage but explicitly require that the developer consider the structure of their code and rely on [structured programming](https://en.wikipedia.org/wiki/Structured_programming) primitives (for loops, functions, and switch statements). The one and only saving grace of `goto` statements is that they allow you write assembly in an HLL when the compiler's optimizer is not up to the task, but this comes at the cost of readability and maintainability. – Parthian Shot Jan 09 '19 at 23:12
  • The reason this is so surprising to find in go is that, in every other case where the golang developers had a choice between structured programming paradigm and "exceptional flow control" / instruction pointer manipulations like `setjmp`, `longjmp`, `goto`, and `try / except / finally` they chose to err on the side of caution. `goto`, fwict, is the sole acquiescence to pre-"structured programming" control flow. – Parthian Shot Jan 09 '19 at 23:20