How to use local go modules with golang with examples
When coding I like to put everything inside of folders depending on what they do. I almost always got specific directories for utils, parser, etc. So here's a complete guide on how to use local go modules with golang
When I started using go modules I was migrating a project from dep which followed this architecture. I had an utils directory, and another directory which handled all parsing for my data input into structs. But then I ended up needing functions from the utils directory. I was stuck and couldn't find how to make directories importable everywhere in the project (like dep used to). Because relative imports are a nightmare with go modules (removing the gopath has a toll after all).
So after quite a bit of fuming and searching all of the web for a solution that is elegant and not something like some crazy relative imports, I found this solution and since I struggled so much to find the solution I figured that I would share it with you all.
The example project
Here's our example project directory structure :
├── go.mod
├── hello
│ ├── go.mod
│ └── hello.go
├── main.go
├── README.md
└── utils
├── go.mod
└── multigreet.go
You can also see the example code on my github repository here : https://github.com/drov0/GolangLocalModulesExample
The code is relatively straightforward : I have two directories, hello and utils that I want to import from the main.go file. And when things get a little tricky is that I want to import the hello directory inside of the utils directory.
The code for the hello.go file that we want to import is this super complicated function :
package hellofunc Hello(name string) string {
return "hello " + name
}The code for the addAndGreet.go file is a bit more complex :
package utils
import (
"example.org/hello"
"strconv"
)
func AddAndGreet(name string, a, b int) string {
return hello.Hello(name) + " " + strconv.Itoa(a + b)
}Notice how we are importing
"example.org/hello"
.Finally here's the main.go file :
package main
import (
"example.org/hello"
"example.org/utils"
"fmt"
)
func main() {
fmt.Println(hello.Hello("martin"))
fmt.Println(utils.AddAndGreet("martin", 2, 3))
}Obviously the modules
example.org/hello
orexample.org/utils
do not exist so these imports make zero sense to our compiler so let's help him out a bitImporting local modules in main.go
So first we simply have to convert all of our directories into go modules. For that we need to add a go.mod at the root of every directories.
Then inside of that go.mod give them whatever name that we want as module name. but bear in mind that it has to be an url. In my example I put this:
module example.org/hello
in the go.mod for the hello directorymodule example.org/utils
in the go.mod for the utils directoryThe import makes a bit more sense now huh ? but we are not done yet.
The replace keyword
This is where the magic happens, go.mod files have a few keywords that can be very useful, one of them is replace what replace does is that it takes a module path (eg : example.org/hello) and replaces it with a direct or relative path.
here's the syntax for the replace keyword :
replace url.com/of/the/module => /direct/path/to/filesNote that replace also works with relative paths.
The main go.mod
module example.com/localmodexample
go 1.13
require (
example.org/hello v0.0.0
example.org/utils v0.0.0
)
replace (
example.org/hello => ./hello
example.org/utils => ./utils
)Usuall go module dependencies work with versions, so to use local go modules with golang you have to set v0.0.0
Finally after the require, I just tell the compiler that those urls are local and can be found in the same directory under
./hello
and./utils
. The great thing about this main go.mod file is that now even the utils module will know where to find the hello module because the url have been replaced.Conclusion
And that's all you need to know to use local go modules with golang. Hopefully this will save you all the hours I put into it. Keep in mind that you can find the complete code on my github : https://github.com/drov0/GolangLocalModulesExample
I know it's been a while since my last post but I got quite busy. But now I should be able to make posts more often on this blog.
Posted from my blog with SteemPress : https://brokencode.io/how-to-use-local-go-modules-with-golang-with-examples/
Upvoted and resteemed
Online Go Compiler: https://repl.it/languages/go It can be useful for small examples
Congratulations @howo!
Your post was mentioned in the Steem Hit Parade in the following category:
You guys make this feel like 1994/95 when I discovered internet browsers and writing code with notepad :) I really like your blog. Very informative. Thank you for all the great shares.
Thanks :)
Congratulations @howo! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Do not miss the last post from @steemitboard:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!