Problems accessing environment variables with Go under macOS

macOS 10.13.3 High Sierra
Golang go1.10rc1

Hello, is anyone aware of any problems with accessing environment variables using Golang under macOS. I’m trying to use the github.com/kelseyhightower/envconfig package. According to the documentation, I should be able to set various variables such as:

export MYAPP_PORT=8080
export MYAPP_USER=Kelsey
export MYAPP_RATE="0.5"
export MYAPP_TIMEOUT="3m"
export MYAPP_USERS="rob,ken,robert"
export MYAPP_COLORCODES="red:1,green:2,blue:3"

And read it with the following code:

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/kelseyhightower/envconfig"
)

type Specification struct {
	Debug      bool
	Port       int
	User       string
	Users      []string
	Rate       float32
	Timeout    time.Duration
	ColorCodes map[string]int
}

func main() {
	var s Specification
	err := envconfig.Process("myapp", &s)
	if err != nil {
		log.Fatal(err.Error())
	}
	format := "Debug: %v\nPort: %d\nUser: %s\nRate: %f\nTimeout: %s\n"
	_, err = fmt.Printf(format, s.Debug, s.Port, s.User, s.Rate, s.Timeout)
	if err != nil {
		log.Fatal(err.Error())
	}

	fmt.Println("Users:")
	for _, u := range s.Users {
		fmt.Printf("  %s\n", u)
	}

	fmt.Println("Color codes:")
	for k, v := range s.ColorCodes {
		fmt.Printf("  %s: %d\n", k, v)
	}
}

It steadfastly refuses to work. Only the zero-values of the struct are returned. I seem to remember I had some issues when I tried to use os.Getenv - I was hoping that this package would correct these problems.

Does anyone know what the problem is here?

What shell are you using? I experience this kind of problem with the fish shell on macOS. I cannot remember having seen this with Bash (I am using a homebrew'ed Bash 4.4 instead of the built-in Bash 3.2.)

And since you are using envconfig: Did you also try native os.Getenv() (to rule out an issue with envconfig)?

How/where have you set the variables? Did you start the go program in the same shell as you set those variables?

Works fine on Mac, of course, although I haven’t used this 3rd party stuff but os.Getenv. Be sure that you export variables in the same shell where your Go executes. This is about UNIX alike systems, not about Mac.

I’m using ZSH as my shell. Supposedly it’s much closed in compatibility to BASH than Fish, but it’s something to investigate. Thanks!

I did try native os.Getenv() as well. No success.

I constructed a shell script consisting of these lines:

export MYAPP_PORT=8080
export MYAPP_USER=Kelsey
export MYAPP_RATE="0.5"
export MYAPP_TIMEOUT="3m"
export MYAPP_USERS="rob,ken,robert"
export MYAPP_COLORCODES="red:1,green:2,blue:3"

I named the script env.sh and did chmod 755 env.sh to make it executable, and I ran it using ./env.sh.

I was careful to run the go program in the same shell (ZSH, this may be significant, I know!).

When you you execute that file it is run in a subshell, the environment is changed only in this subshell and then this subshell will exit in the very same moment as your script exits.

You need to either run those exports directly or source the file, which means that it is run in the current shell and the environment will persist after the script has finished.

$ source env.sh
$ go run your_program.go

This is not related to go, but basic shell 101.

1 Like

That works! Thanks very much.

Synonym for source is dot, so you can also do

. env.sh

There is a space in between.

I had to do . ./env.sh to get it to avoid the path errors, but useful to know, thanks!

By the way, I think the target file doesn’t need to be executive, but I don’t remember, you can try.

Last year I came to *nix type systems via macOS after almost 30 years of DOS/Windoze etc. There’s a lot to learn, isn’t there!!

1 Like

Yes, but you will learn, don’t worry :wink: I use it from ‘99 :smile: Solaris, AIX, FreeBSD, Linux, OSX.

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