Cannot import package variables to main package

I am trying to get values from “custom” package
from %GOPATH%/src/custom/custom.go and print that in main.go file. I have go extension installed in vs code. It removes imports because the package is not correctly imported.
I don’t understand why this isn’t working. I have checked the %GOPATH% and it looks like this “F:\Super\Super\Workspace”
my src folder looks like this
image

package main

import (
“fmt”
“log”
“custom”
)

func main() {

log.Println("gotest")
fmt.Println("text", custom.varone)

}


package custom

const (

varone = "testing"

vartwo = "golang"

)

The name should start with an uppercase letter for it to be exportable.

Varone = "testing"

Vartwo = "golang"

It should’ve worked but the error says.

# command-line-arguments
.\main.go:12:22: undefined: custom.Varone```

After I changed the first word to uppercase.

Your Varone and Vartwo inside custom package must be renamed it to upper case as well. Otherwise, it is not considered to be exported for others to use.

The error you bumped into is the compiler is searching for Varone from custom package but it is unavailable.

Both import and export symbol must be matched with the same name.

Yes I changed to uppercase. My custom package looks like this. But I still get that error.

package custom

const (
	Varone = "testing"
	Vartwo = "golang"
)

Another possible issue is that Go is unable to find/load your custom package.

Go searches for packages first inside $GOROOT/src (which contains builtin packages for Go), then $GOPATH/src .

For you to be able to import the custom package the way you want it, your custom package should be in:
$GOPATH/src/custom/custom.go

In custom.go, you need to specify the package name, and use uppercase for the first letter of the name of the stuff you want to be exported:

package custom

const (
	Varone = "testing"
	Vartwo = "golang"
)

Note that if you will use Go modules, this will not work because modules have a different way of handling dependencies.

(Edit) Was supposed to reply on the topic but clicked the wrong reply button.

Hi, I mistakenly posted without adding /src/ path in my post now I edited it. That’s how I structured custom.go before and changed variable’s first name to UPPERCASE as you’ve said in $GOPATH/src/custom/custom.go. But the error still saying this. I’m not using go modules.

go run main.go
# command-line-arguments
.\main.go:12:22: undefined: custom.Varone

No worries.

Can you structure you folder into the following directory tree, where the main.go is located in its own package directory called myEngine (you can name it anything you want).

$GOPATH
  +-- src/
  |     +-- custom/
  ...   |      +-- custom.go     # defining VarOne and VarTwo constants
        +-- myEngine/
        |      +-- main.go       # holding your main.go
        +--  github.com/
        |      +-- ...
        ...

main.go itself is a package and must be a package. Hence, you can’t place right inside src/ directory.

When not using Go module, your import statement MUST match the exact pathing in $GOPATH/src/.


Backstory

GOPATH idea was to arrange every dependencies to comply into a single unified tree structure so that:

when one imports something like:

github.com/myprofile/pkg/myPackage

# OR

custom

one can simply search the source code easily directory by:

$GOPATH/src/github.com/myprofile/pkg/myPackage

# Respectively...

$GOPATH/src/custom/

This works on paper. However, in practical (as Go communities experienced in the past), the dependencies management was horrible. Say if you want push your main.go package to Github, you need to move the directory into github.com/ and etc.

It was so annoying to the point of creating various workarounds like vendor/ directory, then godep and so on. Then, one day, Go dev team had enough and solve the entire dependency horror with go module feature.

Thank you both for trying to help. Yet this still doesn’t work. Maybe in future I can figure out the cause of this issue myself. I’m using go version go1.15.3 windows/amd64

Okay, I tested your source codes over here with my laptop, it’s working fine for both GO111MODULE in auto and off modes so your codes are not an issue. This downs to 2 more possibilities:

  1. Your entire workspace is not inside GOPATH and you are not using Go module.
  2. Mis-configurations / faulty editor.
Terminal Test Output
u0:src$ tree $GOPATH/src
/home/u0/go/src
├── custom
│   └── custom.go
└── main
    └── main.go

run with GO111Module off mode:

u0:src$ export GO111MODULE=off
u0:src$ go run main/main.go 
2020/11/05 11:39:51 gotest
text testing

run with GO111Module auto mode:

u0:src$ export GO111MODULE=
u0:src$ go run main/main.go 
2020/11/05 11:40:44 gotest
text testing
Detailed Source Codes

content of custom.go:

u0:src$ cat custom/custom.go 
package custom

const Varone = "testing"
const Vartwo = "golang"

content of main.go:

package main

import (
        custom "custom"
        "fmt"
        "log"
)

func main() {
        log.Println("gotest")
        fmt.Println("text", custom.Varone)
}

Let’s root out the first possibility. Can you type the following commands in your editor and state the output please?

> pwd     # or "echo %CD%" or similar. Basically to list out your current directory. I'm not a Windows user =)
...
> go env
...
1 Like

I once initialized go mod after my last reply so there is gomod path in the env. This is what I got:

F:\Super\Super\Workspace\src>go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\user\AppData\Local\go-build
set GOENV=C:\Users\user\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=F:\Super\Super\Workspace\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=F:\Super\Super\Workspace
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=c:\go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=c:\go\pkg\tool\windows_amd64
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\user\AppData\Local\Temp\go-build551321694=/tmp/go-build -gno-record-gcc-switches

This output?

EDIT:

Also, can you use the terminal inside your visual code? this should be the same terminal you execute go run main/main.go.

Yes this is how I’ve been doing it
on vscode
image

Okay, it’s not workspace problem and very likely related to a faulty (can be mis-configured or was not designed for handling GOPATH) vscode editor. Close the old project and delete it your workspace. Your codes are already backup in this thread anyway.

To avoid wasting your learning resources (time and effort) for both long and short run, I will guide you on how to use go module instead of the classical GOPATH. The reason being you won’t be able to get more supports in the future if you stick to the old way.


Go Module Guide

1. Start An Entirely New Project in “My Documents” (outside of GOPATH)

Proceed to create a directory in your "My Documents" as long as it is outside of GOPATH. This will be your new workspace.

FYI, Go module was designed to work outside of GOPATH first the start. Hence, moving forward, you shouldn’t be meddling with GOPATH unless you’re dealing with classical out-of-date Go packages (which you won’t be using them anyway).

The name is recommended to be the same as your package name. There are some rules to it such as:

  1. keep everything lowercase
  2. recommend keeps it to 2-3 syllabus
  3. no space, dash, or underscore

For this example, I will use the package name myproject.

2. Initialize Go Module

Once done, on the terminal, get inside your workspace directory. You always work inside your root workspace.

$ cd <your workspace directory> # Always stay in your workspace's root directory.

Then proceed to initialize the Go module. The command is as follows:

$ go mod init <module name>

The <module name> field varies based on use case. If you’re using Github or Gitlab, then, the field itself is the Github/GitLab pathing to the package.

For this example, I will use my GitLab address so the command is:

$ go mod init gitlab.com/holloway/myproject

If everything is successful, you should get a go.mod file inside your workspace.

myproject/
     +-- go.mod

go.mod file content:

module gitlab.com/holloway/myproject

go 1.15

3. Set Replace Clause (Optional)

To keep the development experience easier, it’s better to set a replace clause and reference your module back to the current working directory. This is to prevent the go module from keep pulling from your remote server every time you compile your codes.

To do that, edit your go.mod and add a replace clause:

replace <module name>  => ./ 

If we continue the example from above, the output should be something like:

module gitlab.com/holloway/myproject

go 1.15

replace gitlab.com/holloway/myproject => ./

At this point, you have a clean working Go module.

4. Test the Go Module with Hello World App

Let’s proceed to test the module. To start, create cmd/<package name> directory inside the workspace to house your main.go package. Then, proceed to create a simple “Hello World” main.go inside it and go run it.

If we follow the example above, you should get something like:

myproject/
     +-- go.mod
     +-- cmd/
          +-- myproject/
                +-- main.go
Simple main.go source code
package main

import (
   "fmt"
)

func main() {
    fmt.Println("Hello World")
}

Then, go run it.

$ go run cmd/myproject/main.go
Hello World
$

If everything is working fine, you now have a confirmed working environment.

5. Create Package Library

Now you can proceed to create your code library and get imported in your main package. To do that, create a simple Consts.go in your root workspace and add your exported variables into it.

If we follow the example above, you should get something like:

myproject
    +-- Consts.go            // **We add the exported constants in this source code**
    +-- go.mod
    +-- cmd/
         +-- myproject/
               +-- main.go

Consts.go source code

package myproject

const (
    // VarOne is first constant to use (document the constant)
    VarOne = "testing"

    // VarTwo is second constant to use (document the constant)
    VarTwo = "golang"
)

6. Import The Constants In Your main.go

Once done, go ahead and edit your main.go again and import those constants. If we follow the example above, your main.go can look something as such:

package main

import (
   "fmt"

   "gitlab.com/holloway/myproject"     // importing as if you're importing from external Github/Gitlab.
)

func main() {
    fmt.Println("Hello World")
    fmt.Println(myProject.VarOne, myProject.VarTwo)
}

FYI:

Because of replace clause, Go module will search from your current directory when you compile the
main.go.

Give it a re-run, and you should get something as such:

$ go run cmd/myproject/main.go
Hello World
testing golang
$

7. Version Control Your Initialization

If you reach this step, you can version control everything as initialize repository. Here is my tested example: https://gitlab.com/holloway/myproject.


Footnote

If your editor still gives you problems, you can do either:

  1. Uninstall cleanly (means delete its %APPDATA% manually) and install again.
  2. Use other editors like notepad++ and command prompt / powershell for go run or compile.
2 Likes

Many thanks. Sorry for late reply. After your suggestion I’ve chosen to use go modules. I’ve seen and tried go modules before even in official go sandbox. But it did not work on vscode on current install. For now I’ve set up a virtual machine in Linux. Go seems to be working just fine with vscode.