Correct way to set Exit Code of Process? - go

In Go what is the proper way to set the exit code of the process?
I tried changing main func to
func main() int {
return -1
}
But this causes error func main must have no arguments and no return values
OK so there is os.Exit(code int), however this immediately aborts the process and does not exit cleanly (no deferreds are run for example).
I also found that panic will exit process and set status code to nonzero, this may be the best way, although it dumps a stack trace to console.
What is the right way to set the exit code?

Make os.Exit the last deferred function executed. Deferred functions are executed immediately before the surrounding function returns, in the reverse order they were deferred. For example,
package main
import (
"fmt"
"os"
)
func main() {
code := 0
defer func() {
os.Exit(code)
}()
defer func() {
fmt.Println("Another deferred func")
}()
fmt.Println("Hello, 世界")
code = 1
}
Output:
Hello, 世界
Another deferred func
[process exited with non-zero status]
Go Playground:
http://play.golang.org/p/o0LfisANwb
The Go Programming Language Specification
Defer statements
A "defer" statement invokes a function whose execution is deferred to
the moment the surrounding function returns, either because the
surrounding function executed a return statement, reached the end of
its function body, or because the corresponding goroutine is
panicking.
DeferStmt = "defer" Expression .
The expression must be a function or method call; it cannot be
parenthesized. Calls of built-in functions are restricted as for
expression statements.
Each time the "defer" statement executes, the function value and
parameters to the call are evaluated as usual and saved anew but the
actual function body is not executed. Instead, deferred functions are
executed immediately before the surrounding function returns, in the
reverse order they were deferred.

Related

Check if function is being called as goroutine or not

Is there any way to find out if a running function was called as goroutine or not?
I've read 'go tour' and I am interested in building a websocket server with golang, so I found this tutorial https://tutorialedge.net/golang/go-websocket-tutorial/
Now I'm wondering if wsEndpoint function from the tutorial is invoked as goroutine (e.g. go wsEndpoint(...)) or not.
I've tried to read http package documentation, but did not get clear picture, just a guess that the handler will be called with go routine. Is that true?
Every function is called from a goroutine, even the main() function (which is called the main goroutine).
And goroutines in Go have no identity. It does not matter which goroutine calls a function.
To answer your "original" question:
Is there any way to find out if a running function was called as goroutine or not?
If we define this as the function being called with the go statement or without that, then the answer is yes: we can check that.
But before we do: I would not use this information for anything. Don't write code that depends on this, nor on which goroutine calls a function. If you need to access a resource concurrently from multiple goroutines, just use proper synchronization.
Basically we can check the call stack: the list of functions that call each other. If the function is at the top of that list, then it was called using go (check note at the end of the answer). If there are other functions before that in the call stack, then it was called without go, from another function (that places before in the call stack).
We may use runtime.Callers() to get the calling goroutine's stack. This is how we can check if there are other functions calling "us":
func f(name string) {
count := runtime.Callers(3, make([]uintptr, 1))
if count == 0 {
fmt.Printf("%q is launched as new\n", name)
}
}
Testing it:
func main() {
f("normal")
go f("with-go")
func() { f("from-anon") }()
func() { go f("from-anon-with-go") }()
f2("from-f2")
go f2("with-go-from-f2")
f3("from-f3")
go f3("with-go-from-f3")
time.Sleep(time.Second)
}
func f2(name string) { f(name) }
func f3(name string) { go f(name) }
This will output (try it on the Go Playground):
"with-go" is launched as new
"from-anon-with-go" is launched as new
"from-f3" is launched as new
"with-go-from-f3" is launched as new
Note: basically there is a runtime.goexit() function on "top" of all call stacks, this is the top-most function running on a goroutine and is the "exit" point for all goroutines. This is why we skip 3 frames from the stack (0. is runtime.Callers() itself, 1. is the f() function, and the last one to skip is runtime.goexit()). You can check the full call stacks with function and file names+line numbers in this Go Playground. This doesn't change the viability of this solution, it's just that we have to skip 3 frames instead of 2 to tell if f() was called from another function or with the go statement.

The deferred call's arguments are evaluated immediately

In A Tour of Go is written:
The deferred call's arguments are evaluated immediately, but the
function call is not executed until the surrounding function returns.
I have difficulty in understanding the first part of the quote. What is called immediately?
func def(s string) func() {
fmt.Println("tier up")
fmt.Println(s)
return func(){ fmt.Println("clean up") }
}
func main() {
defer def("defered line")()
fmt.Println("main")
}
//Output:
//tier up
//defered line
//main
//clean up
https://play.golang.org/p/Av3mAEXxA4R
What is deferred here and what is evaluated immediately?
To learn how defer and evaluations work, first let's look at the Spec: defer statements:
Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.
Both the function value (whose call is deferred) and its parameters are evaluated. But the deferred function is not yet called.
Let's iterate toward your example with small steps:
defer f("a")
In this case the function value is evaluated (which will be f), and the parameters are evaluated, which is a constant, so that's gonna be "a".
Next step:
defer f(g("a"))
In this case the function value is evaluated (which will be f), and the parameters are evaluated, which means g will be called with "a" (because g's return value is the param to f).
Next step:
defer f()()
This is valid if the f function returns a function. The function value will be evaluated (which means f will be called!) but its return value will not be called, that is what will be deferred.
defer f(g())()
In this case the deferred function is the return value of f, so to evaluate the deferred function value, f must be called, and to do that g must be called prior. The return value of f will be deferred (not called).
Back to your example:
defer def("defered line")()
The function value is evaluated, which is the return value of def, so def is called. The return value of def will be deferred. Its parameters are evaluated, but actually it has no parameters.
So logically this is what happens:
The deferred function value is evaluated, which requires that:
def function must be called, which requires that:
Params to def are evaluated, it's a constant: "defered line"
Parameters to the deferred function are evaluated; since there are no params to it, this step is done.
This is what happens sequentially if we lay out the above structure:
Param to def is evaluated: it's a constant "defered line"
def is called which prints tier up and its argument: defered line
The return value of def is not called, that is what's deferred.
Function main prints: main
Function main returns, so deferred functions are called now. The deferred function prints clean up
The deferred call's arguments are evaluated immediately, but the
function call is not executed until the surrounding function returns.
Above sentence means the deferred function arguments are evaluated at the line where they are deferred but the function will run after the surrounding function which is main returns.
A defer statement pushes a function call onto a list. The list of
saved calls is executed after the surrounding function returns. Defer
is commonly used to simplify functions that perform various clean-up
actions.
Deferred function calls are executed in Last In First Out order after the surrounding function returns.
Deferred functions may read and assign to the returning function's named return values.
The above line clearly states that it will return the value to the main function.
For eg:-
func c() (i int) {
defer func() { i++ }()
return 1
}
Above function will return 2 value rather than 1. That's why this line
return func(){ fmt.Println("clean up") }
will be called in the last.
For more information on defer. Please read golang blog for defer
It will be more clear if you change the argument you're passing to def(string) from a string literal (evaluated at compile time) to something more interesting, say:
func bar(s sting) string {
return s + " bar "
}
func main() {
defer def(bar(os.Args[1]) + "defered line")()
fmt.Println("main")
}
When the defer def(bar(os.Args[1]) + "defered line")() statement
is executed, the argument to def will be fully evaluated,
and this means calling bar passing it the first command-line
argument supplied by the user when running your program,
taking whatever bar returned and appending
a string literal to it.
The resulting string is then saved, and will be passed to def
when it will run.
In
defer def("defered line")()
def("defered line") and () are deferred call's arguments evaluated immediately.
def("defered line") evaluates to func(){ fmt.Println("clean up") } with side effects.

Querying ProcessState

I have a simple program and runs an exe and checks the Exited value afterwards, but it is giving me an "panic: runtime error: invalid memory address or nil pointer dereference" error, any idea why?
package main
import (
"fmt"
"os/exec"
"time"
)
func main() {
prog:= exec.Command("path\to\exe")
prog.Dir = "path\to"
go prog.Run()
fmt.Println(prog.ProcessState.Exited())
time.Sleep(500 * time.Second)
}
The documentation says:
ProcessState contains information about an exited process available after a call to Wait or Run.
The main goroutine accesses the ProcessState field before the field is set to a non-nil value by the call to Run() in the goroutine. The call to Exited() panics as a result.
A simple fix is to call Run() from the main goroutine.

How to implement a PHP function `die()` (or `exit()`) in Go?

In PHP, die() is used to stop running the script for preventing the unexpected behaviour. In Go, what is the idiomatic way to die a handle function? panic() or return?
You should use os.Exit.
Exit causes the current program to exit with the given status code.
Conventionally, code zero indicates success, non-zero an error. The
program terminates immediately; deferred functions are not run.
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("Start")
os.Exit(1)
fmt.Println("End")
}
Even, you can use panic, it's also stop normal execution but throw Error when execution stop.
The panic built-in function stops normal execution of the current
goroutine. When a function F calls panic, normal execution of F stops
immediately. Any functions whose execution was deferred by F are run
in the usual way, and then F returns to its caller. To the caller G,
the invocation of F then behaves like a call to panic, terminating G's
execution and running any deferred functions. This continues until all
functions in the executing goroutine have stopped, in reverse order.
At that point, the program is terminated and the error condition is
reported, including the value of the argument to panic. This
termination sequence is called panicking and can be controlled by the
built-in function recover.
package main
import "fmt"
func main() {
fmt.Println("Start")
panic("exit")
fmt.Println("End")
}
If you don't want to print a stack trace after exiting the program, you can use os.Exit. Also you are able to set a specific exit code with os.Exit.
Example (https://play.golang.org/p/XhDkKMhtpm):
package main
import (
"fmt"
"os"
)
func foo() {
fmt.Println("bim")
os.Exit(1)
fmt.Println("baz")
}
func main() {
foo()
foo()
}
Also be aware, that os.Exit immediately stops the program and doesn't run any deferred functions, while panic() does. See https://play.golang.org/p/KjGFZzTrJ7 and https://play.golang.org/p/Q4iciT35kP.
You can use panic in HTTP handler. Server will handle it. See Handler.
If ServeHTTP panics, the server (the caller of ServeHTTP) assumes that the effect of the panic was isolated to the active request. It recovers the panic, logs a stack trace to the server error log, and hangs up the connection.
Function panic is reserved for the situation when program just cannot continue. Inability to serve just one request is not the same as inability to continue to work, so I would log the error, set a correct HTTP status and use return. See Effective Go.
The usual way to report an error to a caller is to return an error as an extra return value. The canonical Read method is a well-known instance; it returns a byte count and an error. But what if the error is unrecoverable? Sometimes the program simply cannot continue.
The idiomatic way to break a function in Go is to use panic(). This is the defacto way to stop the execution of an event on runtime. If you want to recover the panic you can use the built in recover() function.
Panic explanation:
Panic is a built-in function that stops the ordinary flow of control
and begins panicking. When the function F calls panic, execution of F
stops, any deferred functions in F are executed normally, and then F
returns to its caller.
https://blog.golang.org/defer-panic-and-recover
Recover explanation:
Recover is a built-in function that regains control of a panicking
goroutine. Recover is only useful inside deferred functions. During
normal execution, a call to recover will return nil and have no other
effect. If the current goroutine is panicking, a call to recover will
capture the value given to panic and resume normal execution.
https://blog.golang.org/defer-panic-and-recover
And here is a simple example:
package main
import "fmt"
func badCall() {
panic("Bad call happend!")
}
func test() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("Panicking %s\n\r", err)
}
}()
badCall()
fmt.Println("This is never executed!!")
}
func main() {
fmt.Println("Start testing")
test()
fmt.Println("End testing")
}

Is there idiomatic scoped semantics in golang?

I wonder if there is any idiomatic way to represent scoped semantics. By scoped I mean things like:
scoped mutex (oneliner instead of explicit Lock + deffered Unlock),
logging function (or any code block) entrance and exit,
measuring execution time.
Example code for first two bullets:
package main
import "log"
import "sync"
func Scoped(m *sync.Mutex) func() {
m.Lock()
return func() {
m.Unlock()
}
}
func Log(what string) func() {
log.Println(what, "started")
return func() {
log.Println(what, "done")
}
}
func main() {
defer Log("testing")()
m := &sync.Mutex{} // obviously mutex should be from other source in real life
defer Scoped(m)()
// use m
}
https://play.golang.org/p/33j-GrBWSq
Basically we need to make one function call just now (eg mutex lock), and one call should be postponed to defer (eg mutex unlock). I propose just returning unnamed function here, but it can be easily named (return struct with function field).
There is only one problem: user can forget to 'call' result of first call.
This code is (can be) idiomatic?
Take anonymous function as a scope:
func() {
Entrance()
defer Exit()
// anything you want to do in this scope
}()
Your proposed solution is already nice. You return a value of func type which you also have to call at the end of the defer.
You can avoid that (returning a func value), but there have to be 2 function calls, one that logs the start event and another one that logs the end event.
The alternative is to make a function call which produces the parameter value of the function that is deferred (rather than returning a function) which is evaluated with the defer statement, and this way it still can remain one line.
You can also try it on the Go Playground:
func start(s string) string {
fmt.Println("Started", s)
return s
}
func end(name string) {
fmt.Println("Ended", name)
}
func main() {
defer end(start("main"))
fmt.Println("Doing main's work...")
}
Output:
Started main
Doing main's work...
Ended main
I do not believe there is an idiomatic way to do this. I'm not sure why you'd want to either, is it really so bad to write
m.Lock()
defer m.Unlock()
?
I think question isn't relevant to Go idiomaticity, Seems it's generally better to reason about code when function behave identically either call. To keep state I'd better make an object and define function as method on that object. Means something like
type message string
func (foo message) Log(bar string){
if bar==nil{doSomethingSpecial()}
switch foo{
case something: doSomething()
...
case nil: doSomethingInitial()
default: doDefault()
}
log.Println(bar, "started")
foo=bar
}

Resources