-2

go 1.12 window

misplaced a fmt.Println after os.Exit instead of before, shouldn't this have gotten a compiler failure or at least warning?

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println("Hello, playground")
    os.Exit(0)
    fmt.Println("Good By, playground")
}
sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • 5
    It might be caught by a linter, but the compiler doesn't care about semantics. You have 3 function calls, which is legal. You can't have a `return` followed by more code, but to the compiler `os.Exit` is just another function. – Adrian May 29 '19 at 19:45
  • @Adrian Actually in Go it is not an error to have code after a `return`. – icza May 29 '19 at 21:45
  • @icza sorry you're right, I forgot Playground runs `go vet` before `go run`. – Adrian May 30 '19 at 13:27

1 Answers1

4

os.Exit() is just like any other function, the compiler should not know it terminates the app and so the rest of the code that follows is unreachable. os.Exit() is just one example and there are more, e.g.log.Fatal() (which calls os.Exit()). Not to mention you can also create a function which calls one of these, how far should the compiler go to detect all or most of these?

Going further, the Go compiler does not detect nor marks "truly" unreachable code. The following variation when using a return statement could even be obvious to the compiler:

func main() {
    fmt.Println("Hello, playground")
    return
    fmt.Println("Good By, playground")
}

Yet it compiles and runs just fine, and outputs (try it on the Go Playground):

Hello, playground

So the compiler does not detect unreachable code, but go vet does, which is also run by the Go Playground, and so you can see the app's output prefixed by:

./prog.go:10:2: unreachable code
Go vet exited.

This has been brought up before, see cmd/gc: report unreachable code #9501. Robert Grisemer's response was:

Generally, Go's philosophy is not to protect the programmer at all costs from his/her mistakes. It's deliberate to not raise an error for unreachable code. It's also not a very common kind of mistake. Besides, it's often useful to introduce early returns for debugging which may cause plenty of unreachable code. It's not clear the benefits outweigh the costs and disadvantages.

Unused variables can lead to subtle find bugs in conjunction with Go's re-declaration mechanism in short variable declarations - hence the error message for unused variables. This is a mechanism that evolved from experience and is a pragmatic solution for a concrete problem.

Unused imports are reported because it helps keeping dependencies under control - an important tool in large-scale systems design and as a side-effect it also keeps compile times fast. Again a very deliberate design decision.

Finally, making dead code an error would be a significant language change which is out of the question at this point.

Use go vet.

Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827