Could not import local modules in Golang

Ayman Arif picture Ayman Arif · Mar 14, 2020 · Viewed 11.3k times · Source

I am trying to import local modules, but I am unable to import it using go mod. I initially built my project using go mod int github.com/AP/Ch2-GOMS

Note my environment is go1.14 and I am using VSCode as my editor.

This is my folder structure

Ch2-GOMS
│   ├── go.mod
│   ├── handlers
│   │   └── hello.go
│   └── main.go

My main.go code:

package main

import (
    "log"
    "net/http"
    "os"

    "github.com/AP/Ch2-GOMS/handlers" // This gives "could not import github.com/AP/Ch2-GOMS/handlers" lint error
)

func main() {

    l := log.New(os.Stdout, "product-api", log.LstdFlags)
    hh := handlers.NewHello(l)

    sm := http.NewServeMux()
    sm.Handle("/", hh)

    http.ListenAndServe(":9090", nil)
} 

I cannot see auto-complete for my local modules such as handlers.NewHello.

go build generated go.mod contents:

module github.com/AP/Ch2-GOMS
go 1.14

I am also getting You are neither in a module nor in your GOPATH. Please see https://github.com/golang/go/wiki/Modules for information on how to set up your Go project. warning in VScode, even though i have set GO111MODULE=on in my ~/.bashrc file

Answer

shmsr picture shmsr · Mar 14, 2020

Read: Ian Lance Taylor's comment (Go's Core Team)

I know of three ways:

  • Method 1 (The best way):
# Inside
# Ch2-GOMS
# │   ├── go.mod
# │   ├── handlers
# │   │   └── hello.go
# │   └── main.go

# In Ch2-GOMS
go mod init github.com/AP/Ch2-GOMS

# In main.go
# Add import "github.com/AP/Ch2-GOMS/handlers"
# But, make sure: 
# handlers/hello.go has a package name "package handlers"

You must be doing something wrong and that's why it's not working.

  • Method 2 (The good way):
# Inside
# Ch2-GOMS
# │   ├── go.mod
# │   ├── handlers
# │   │   └── hello.go
# │   └── main.go

# Inside the handlers package
cd Ch2-GOMS/handlers
go mod init github.com/AP/Ch2-GOMS/handlers # Generates go.mod
go build # Updates go.mod and go.sum

# Change directory to top-level (Ch2-GOMS)
cd ..
go mod init github.com/AP/Ch2-GOMS # Skip if already done
go build # Must fail for github.com/AP/Ch2-GOMS/handlers
vi go.mod

Inside Ch2-GOMS/go.mod and add the following line:

# Open go.mod for editing and add the below line at the bottom (Not inside require)
replace github.com/AP/Ch2-GOMS/handlers => ./handlers

# replace asks to replace the mentioned package with the path that you mentioned
# so it won't further look packages elsewhere and would look inside that's handlers package located there itself
  • Method 3 (The very quick hack way for the impatient):

    1. Turn off Go Modules GO111MODULE=off
    2. Remove go.mod file
# Check: echo $GOPATH

# If $GOPATH is set
mkdir -p $GOPATH/src/github.com/AP/Ch2-GOMS
cd $GOPATH/src/github.com/AP/Ch2-GOMS


# If $GOPATH is unset
mkdir -p ~/go/src/github.com/AP/Ch2-GOMS
cd ~/go/src/github.com/AP/Ch2-GOMS

# Now create a symbolic link
ln -s <full path to your package> handlers

Reason: During the build, the compiler first looks in vendor, then GOPATH, then GOROOT. So, due to the symlink, VSCode's go related tools will also work correctly due to the symlink provided as it relies on GOPATH (They don't work outside of GOPATH)