Hi new at go, here. I’d like some input on a super simple go function that reads a user’s config file and exits 1 if there’s some kind of problem opening/reading it. Eventually I will obviously parse the JSON, but being new to go, wanted to start off simple and see if I am on the right track idiomatically. Is this idiomatic, in that the programmer has to keep checking for errors as they go? I don’t like err2 variable name. I generally wouldn’t use pointers unless I needed to, and would rather return a string. Is this the idiomatic way to return an optional string? It seems unduly verbose to me.
Any comments are welcome.
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path"
)
// Attempts to read the .sinkerrc.json file in the user's
// home directory as a pointer to a string.
func readSinkerRc() (*string, error) {
homdir, err := os.UserHomeDir()
if err != nil {
// problem getting homedir
return nil, err
}
dat, err2 := ioutil.ReadFile(path.Join(homdir, ".sinkerrc.json"))
if err2 != nil {
// Problem reading file.
return nil, err2
}
ret := string(dat)
// return a pointer to the data so we could also return nil for error case.
return &ret, err
}
func main() {
dat, err := readSinkerRc()
if err != nil {
log.Fatal("Problem reading your .sinkerrc.json file: " + err.Error())
}
fmt.Println(*dat)
}
Some thoughts: You don’t need to rename err, but yes, you should check for errors at each point an error could occur. I also took out the pointers and made sure strings are returned at each point.
I see so since we are only checking for err, no need to return nil for the string and using empty string simplifies and allows us to avoid pointer and type the first ret val as string.
It’s interesting that somewhat exceptional conditions are dealt with first in the flow. E.g. most of the time the system can read the user’s home dir. This is kind of opposite to what I’ve been taught generally, which is to deal with the normative case first.
In the case of go, we usually deal with error cases first? You could also check that err is nil, compute, then at the end deal with when it is not nil, but that’s generally not done?