Load a package created locally with Go Module

I started studying Go. I'm studying using books, but basically the version is old. Therefore, most of the files are not structured using Go Module.

However, it seems that the trend will be to use Module in future version upgrades. So, even a beginner wanted to develop using Module, so I was crazy, but I had a harder time than I thought ...

Especially, I had a hard time not knowing how to import a locally created package to another file. I decided to write an article to reduce the number of people who suffer from the same error.

What is Go Module?

A package management tool. Before Go 1.11, you couldn't handle locally created packages unless you put the source code under $ GOPATH / src /, but if you use go module, you can manage packages from any directory. It seems that it has become possible. Is it something like node package.json? Therefore, it is possible to create a project without depending on the path of environment variables.

Introduction

Version

❯ go version
go version go1.15.3 darwin/amd64

Set GO111MODULE to on or auto in go env I was doing it on.

❯ go env -w GO111MODULE=on
❯ go env
GO111MODULE="on"

The file structure looks like this. The code itself is pretty simple.

I was addicted to the fact that each package requires one go.mod ...

go_module/
 ├ hello/
 ├  └ hello.go
 ├  └ hello_test.go
 ├  └ go.mod
 ├ goodbye/
 │ └ goodbye.go
 │ └ go.mod
 └ main/
   └ main.go
   └ go.mod

First, make each package package hello

hello.go


package hello

func Hello() string {
	return "Hello World"
}

I will also make a test for the time being.

hello_test.go


package hello

import (
	"testing"
)

func TestHello(t *testing.T) {
	got := Hello()
	want := "Hello World"

	if got != want {
		t.Errorf("got %q want %q", got, want)
	}
}

package goodbye

goodbye.go


package goodbye

func Goodbye() string {
	return "Goodbye!!"
}

package main

main.go


package main

import (
	"fmt"
	"goodbye"
	"hello"
)

func main() {
	fmt.Println(hello.Hello())
	fmt.Println(goodbye.Goodbye())
}

Now that the source code is OK, let's start main.

❯ go run main.go
main.go:5:2: package goodbye is not in GOROOT (/usr/local/Cellar/go/1.15.3/libexec/src/goodbye)
main.go:6:2: package hello is not in GOROOT (/usr/local/Cellar/go/1.15.3/libexec/src/hello)

You get angry if you don't have the package of the file you're importing. Create modules in all directories. It seems that Module cannot be created unless you go to each directory.

❯ go mod init main
go: creating new go.mod: module main

❯ cd hello && go mod init hello
go: creating new go.mod: module hello

❯ cd ../goodbye && go mod init goodbye
go: creating new go.mod: module goodbye

Let's start with this

❯ go run main.go 
main.go:5:2: package goodbye is not in GOROOT (/usr/local/Cellar/go/1.15.3/libexec/src/goodbye)
main.go:6:2: package hello is not in GOROOT (/usr/local/Cellar/go/1.15.3/libexec/src/hello)

You're still angry. This is because the import written in main.go is not linked to the module created earlier. It is necessary to define each module with the path used in the file being imported.

So let's define the hello module and the goodbye module in ** main go.mod ** with relative paths.

go.mod



module main

go 1.15

replace hello => ../hello
replace goodbye => ../goodbye

Let's start main again

❯ go run main
go: found goodbye in goodbye v0.0.0-00010101000000-000000000000
go: found hello in hello v0.0.0-00010101000000-000000000000
Hello World
Goodbye!!

I was able to start it! Now let's take a look at go.mod in package main.

go.mod



module main

go 1.15

replace hello => ../hello

replace goodbye => ../goodbye

require (
	goodbye v0.0.0-00010101000000-000000000000
	hello v0.0.0-00010101000000-000000000000
)

require was added automatically. This seems to be the version of the dependent module, which is the same as package-json.lock in package.json. This time it is a local module, but if you import the module on github, the version will come out like this.

require github.com/aws/aws-lambda-go v1.13.2

This time I tried to make it possible to import local packages with go module in a nice way. If there is any good way, please let me know!

Postscript

If the package structure is as follows, go.mod can be main only. With this configuration, the main package contains the hello package and the goodbye package.

go_module/
 ├ hello/
 ├  └ hello.go
 ├  └ hello_test.go
 ├ goodbye/
 │ └ goodbye.go
 └ main.go
 └ go.mod

As a point, please describe the path from main when importing with main.go.

main.go


package main

import (
	"fmt"
	"main/goodbye"
	"main/hello"
)

func main() {
	fmt.Println(hello.Hello())
	fmt.Println(goodbye.Goodbye())

Now you can start go run main! Thank you @nobonobo! !!

Reference site https://qiita.com/uchiko/items/64fb3020dd64cf211d4e https://takeai.silverpigeon.jp/handling-local-packages-with-go-mod/

Recommended Posts

Load a package created locally with Go Module
Steps to install a Git cloned package locally with pip
Go language-standard package
[Go] Execution / build / package test
Go Language-Basic ❶
Go language-fmt.Scan
Go language-address
Go Language-Functions
Go language-pointer
Go Language-Basic ❷
GO Chokisomemo 1
Go language-iteration
Load a package created locally with Go Module
How to add a package with PyCharm
Created a darts trip with python (news)
Start a temporary http server locally with Pytest
Create a GUI executable file created with tkinter
A memo created in a package and registered in PyPI
A simple to-do list created with Python + Django
Configure a module with multiple files in Django
Try drawing a map with Python's folium package
Python with Go
Go language-standard package
A memo of misunderstanding when trying to load the entire self-made module with Python3
A story about an error when loading a TensorFlow model created with Google Colab locally
use go module
Created a module to monitor file and URL updates
[Linux] [kernel module] Build and load a simple loadable kernel module
Load the module with the same name in another location
Deploy a web app created with Streamlit to Heroku