When to use panic, log.Fatal() and just a blank return

Hi, i’m creating a small app in golang and i’m wondering when to use log.Fatal(), panic and just print the error and return the function without panicking.

For example:

//Configuration represents the data that will be read from the yaml config file
type Configuration struct {
    Certificate      string `yaml:"Certificate"`
    Key              string `yaml:"Key"`
    Hostname         string `yaml:"Hostname"`
    Port             string `yaml:"Port"`
    ConnectionString string `yaml:"ConnectionString"`
    DbType           string `yaml:"DbType"`
}

//SetConfiguration gets configuration from a yaml config file.
func SetConfiguration() *Configuration {
  config := new(Configuration)

  data, err := ioutil.ReadFile("config/server.yml")
  if err != nil {
	 log.Fatal(err)
 }

   ok := yaml.Unmarshal(data, config)
   if ok != nil {
	 log.Fatal(err)
   }

 return config
}

i guess it should be log.Fatal() because it fails to open a file that the whole program depends on

I’m not using golangs logger, so. So I rephrase the question to:

When to print, when to print and exit and when to return with error?

I usually print an error when I either can recover easily or when I can fallback to something else. Eg. I can not reach the database, but I can try again in a couple of milliseconds.

I print and exit when I’m unable to recover. Eg I can not open important configuration files.

I do return when I’m not in the main control loop of the application or when I’m writing library code, as I hate when libraries just print into my precious stdout with weird formatting and without any structure (I’m mostly logging JSON)

1 Like

As this is a method, I would not panic but return an error and decided in the caller code what to do. If you decide to panic you should rename your method to MustSetConfiguration.

1 Like

Thanks for the descriptive and helpful answer :slightly_smiling_face: . But i’m wondering why you don’t use logger

Log.Fatal is not logger, it’s just another kind of panic, we don’t want our libraries to panic (stop execution).

1 Like

So the way i should do it is to always try to recover the error if possible?

I wrote above, return errors from your methods and functions and panic in the main() function if you can’t initialize for example.

It is commonly accepted that libraries should not use panic, but if calling log.Fatal has the same effect, surely this should also be outlawed.

https://dave.cheney.net/2015/11/05/lets-talk-about-logging

1 Like

That’s actually a pretty useful web site and explanation thanks for the help :heart: !

Here is one more

https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully

1 Like

Because structured logging into JSON is a requirement in my area, that’s hard to achieve with the standard logger. Also I find zaps approach very nice when adding arbitrary metadata.

1 Like

Thank you all of the great responses i love this community :heart: !

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.