-2

I have the following code:

main.go:

package main

import (
    "fmt"

    "./globalvar"

    "github.com/Denton-L/gotest/usevar"
)

func main() {
    globalvar.GlobalNum = 42
    fmt.Println(globalvar.GlobalNum)
    usevar.PrintGlobal()
}

usevar/usevar.go:

package usevar

import (
    "fmt"

    "github.com/Denton-L/gotest/globalvar"
)

func PrintGlobal() {
    fmt.Println(globalvar.GlobalNum)
}

globalvar/globalvar.go:

package globalvar

var GlobalNum int

and I'm compiling with go build main.go. When I run ./main, I get

42
0

as output but I am expecting

42
42

Why is this happening?

EDIT: Note that I'm able to access the global variables but they contain unexpected values so this is not a duplicate of Golang Global Variable access.

Denton L
  • 15
  • 1
  • 3
  • 3
    Aside from whether this is even a good idea, `"./globalvar"` and `"github.com/Denton-L/gotest/globalvar"` are 2 different packages. _Never_ use relative paths for imports. – JimB Mar 01 '19 at 23:50
  • I don't think it's a duplicate issue because that other issue doesn't mention mixing local and non-local imports. Anyway, I wanted to self-answer this question because I couldn't find any other posts about this and hopefully, I'll be able to save someone else some time. (Or maybe myself in the future ;) ) – Denton L Mar 01 '19 at 23:56
  • There are no local imports, so mixing them isn't a possibility. – Jonathan Hall Mar 02 '19 at 09:01

1 Answers1

-2

The reason why this is happening is because we're mixing relative and remote imports. In main.go, the globalvar package is imported as ./globalvar but usevar/usevar.go imports it as github.com/Denton-L/gotest/globalvar. Therefore, Go considers these to be separate packages with their own namespaces and thus, they have their own separate global variables that happen to be named identically.

In order to solve this, change the relative import to be a remote import, so the main.go import statement should look like this:

import (
    "fmt"

    "github.com/Denton-L/gotest/globalvar"
    "github.com/Denton-L/gotest/usevar"
)

This will let the compiler know that they are actually the same package and, thus, the global variable will be shared.

Denton L
  • 15
  • 1
  • 3
  • "Local imports" aren't a thing in Go, and only work kind of by accident, in some cases. Never use them. – Jonathan Hall Mar 02 '19 at 09:02
  • Sorry, my mistake. I guess they're called "relative imports" instead of local. https://golang.org/cmd/go/#hdr-Relative_import_paths – Denton L Mar 03 '19 at 18:35
  • The key from that documentation is "Second, if you are compiling a Go program not in a work space, you can use a relative path in an import statement in that program to refer to nearby code also not in a work space." In other words, only use relative imports if you're not in a work space, and working on a tiny/test program. In other words: rarely or never, and that case clearly doesn't apply to you. – Jonathan Hall Mar 03 '19 at 19:01