ChatGPT解决这个技术问题 Extra ChatGPT

What are the differences in outcome for panic vs log.Fatalln()?

go

From the documentation on log.Fatalln():

func Fatalln(v ...interface{}) Fatalln is equivalent to Println() followed by a call to os.Exit(1).

The source code for Fatalln:

   310  // Fatalln is equivalent to Println() followed by a call to os.Exit(1).
   311  func Fatalln(v ...interface{}) {
   312      std.Output(2, fmt.Sprintln(v...))
   313      os.Exit(1)
   314  }

It seems the main difference is whether or not the error is recoverable (since you can recover a panic) - is there anything more significantly different between these?

Panic's interface definition is:

   215  // The panic built-in function stops normal execution of the current
   216  // goroutine. When a function F calls panic, normal execution of F stops
   217  // immediately. Any functions whose execution was deferred by F are run in
   218  // the usual way, and then F returns to its caller. To the caller G, the
   219  // invocation of F then behaves like a call to panic, terminating G's
   220  // execution and running any deferred functions. This continues until all
   221  // functions in the executing goroutine have stopped, in reverse order. At
   222  // that point, the program is terminated and the error condition is reported,
   223  // including the value of the argument to panic. This termination sequence
   224  // is called panicking and can be controlled by the built-in function
   225  // recover.
   226  func panic(v interface{})

It appears panic does not return anything.

Is that the primary difference? Otherwise, they seem to perform the same function in an application, assuming the panic is not recovered.

Consider reading official go blog, where panic & recover are well explained
A common opinion is that you should never use either. dave.cheney.net/2015/11/05/lets-talk-about-logging
After reading the Go blog it seems that Panic behaves kind of like Exceptions, it bubbles up the execution stack until caught by a Recover. In general, don't panic unless you implement a Recover as well. Never log.Fatal in libraries. Always return nil,false or an error depending on the situation
@francojposa Right. As the comment says: The article is about using neither.
@francojposa: If you believe there's incorrect information in the post, I would encourage you to tell the author. Dave is very personable. And most of what he says about Go very quickly becomes "common opinion" if it wasn't already.

J
JimB

The log message goes to the configured log output, while panic is only going to write to stderr.

Panic will print a stack trace, which may not be relevant to the error at all.

Defers will be executed when a program panics, but calling os.Exit exits immediately, and deferred functions can't be run.

In general, only use panic for programming errors, where the stack trace is important to the context of the error. If the message isn't targeted at the programmer, you're simply hiding the message in superfluous data.


So in the context of tests it seems panic would be better then? Because they are targeted towards programmers..
@enderland: only panic if the stack trace is relevant (I know I don't want useless stack traces when testing, when a simple message about the failure would suffice). If you only need to write an error message, then just write that message. (also, use t.Fatal/t.Fatalf vs log in tests when possible)
The fact that Fatal doesn't execute defers is a huge problem IMO, I can't see how this makes it a viable solution. For example because of that my program does not cleanup its temporary directories…
If the function that deals with the temp directories returns an error, then defer will be called and it is the responsibility of the caller to decide if log.Fatal is needed. Maybe?
Just came here because Fatal not calling defer resulted in resources (like database) not being cleaned up. I think in general, Fatal should be avoided in favor of Panic. Only use Fatal if you know for sure there's no defer in the code including dependencies.
m
mroman

panic is often used in little programs to just terminate the program once an error appears you don't know how to handle or don't want to handle. The downside of panic is exactly that: it'll terminate the program (mostly, unless you use recover). It's generally not good to use panic unless you intend to recover from it or unless something has happened you really can't recover from at all nor where you can gracefully terminate the program otherwise. Consider for example an API that offers you functionality but that API secretly has a panic somewhere and you notice that your program terminates in production due to this. Thus, the "outward API" of whatever code you write should recover from panics and return an error instead. The same thing applies to anything that terminates the program.

However, os.Exit() can't be recovered from nor does it execute defers.