I’ve never programmed in a language with pointers before. I wrote this code and I’m not actually sure why it works:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"path"
)
type Gist struct {
AccessToken string
Files []string
}
type Conf struct {
Gist Gist
}
// Attempts to read the .sinkerrc.json file in the user's
// home directory
func ReadSinkerRc() ([]byte, error) {
homdir, err := os.UserHomeDir()
if err != nil {
return nil, err
}
data, err := ioutil.ReadFile(path.Join(homdir, ".sinkerrc.json"))
if err != nil {
return nil, err
}
return data, nil
}
// Parses the json from the config.
func ParseJsonConfg(data []byte) (Conf, error) {
var conf Conf
err := json.Unmarshal(data, &conf)
return conf, err
}
// Gets the configuration data, taking care of reading
// and parsing the json from the config file
func Get() (*Conf, error) {
data, err := ReadSinkerRc()
if err != nil {
return nil, err
}
conf, err := ParseJsonConfg(data)
if err != nil {
return nil, err
}
return &conf, nil
}
func main() {
config, err := Get()
if err != nil {
log.Fatal(err.Error())
}
fmt.Println(config.Gist.AccessToken)
}
Get
returns a pointer to a Conf
and an error because otherwise we can’t express a nil Conf
, but we can express a nil pointer because the default 0 value of a pointer is nil
. And there is no way to have a nil value of a struct, right? If so, why not?
What I don’t understand is that if Get
returns a memory address to a Conf
and an error, why in main
I can access its properties of Conf
without getting its underlying value? Why don’t I need to do *conf
to get the underlying value?