Go 'mod init' creating new folders? what is the significance of path? - go

Just 3 days experience in Go language. Hope an example will be more apt to understand my confusion.
root#freebsd1:/usr/home/arun/go-start/src/test2 # go mod init f1/f2/f3/f4/f5/hello
go: creating new go.mod: module f1/f2/f3/f4/f5/hello
root#freebsd1:/usr/home/arun/go-start/src/test2 #
Here in above example go mod init is creating all these folders(f1/f2/f3/f4/f5/hello)?. I searched a lot, couldn't find any such folders in system. Then what is the significance of this path.
Even though below command will not run if this path is not mentioned as it is
# go install f1/f2/f3/f4/f5/hello
--:EDIT:--
May be this will help someone later ( Just walk through the steps to understand this in a proper way, especially for newbies )
I am planning to create a program 'calculator' and will upload in GitHub later.
I will keep the functions in different packages like sum,multiply etc
first step #go mod init github.com/go-arun/calculator( Don't confuse here , this is just an assumption that, in future I may create a repository in github for this project )
created folder sum(one of the package folder , and created sum.go inside )
See those in by system:
1.
root#debian1:/home/arun/lab# go mod init github.com/go-arun/calculator
go: creating new go.mod: module github.com/go-arun/calculator
root#debian1:/home/arun/lab# cat go.mod
module github.com/go-arun/calculator
go 1.15
2.
root#debian1:/home/arun/lab# cat sum/sum.go
package sum
import "fmt"
func Sum(num1,num2 int)(){
fmt.Println(num1+num2)
}
3.
root#debian1:/home/arun/lab# cat main.go
package main
import(
"github.com/go-arun/calculator/sum"
)
func main(){
n1 := 10
n2 := 10
sum.Sum(n1,n2)
}
4.
root#debian1:/home/arun/lab# tree
.
|-- go.mod
|-- main.go
`-- sum
`-- sum.go

go mod init does not create those folders. You pass the "module path" to go mod init which is recorded in the go.mod file it creates.
The "module path" is the import path prefix corresponding to the module root. The module path and the relative path to the module root together form the complete import path which must be unique in an app.
So for example if your module contains a folder named foo (and a package foo in it), it is imported by a path being modulepath/foo. In your case it would be f1/f2/f3/f4/f5/hello/foo.
It is allowed for moduleA to contain a foo package, and also for moduleB to have a foo package. When used / imported, first would be imported like moduleA/foo the latter like moduleB/foo, so it's unambiguous which one you're importing. The module path is like a namespace.
It's recommended to use a module path that corresponds to a repository you plan or will publish your module to, so when you do, go get will be able to automatically fetch, build and install your module. For example you may choose a module path github.com/bob/hello, so when you publish your module, everyone can get it by simply using import "github.com/bob/hello" in their app.
Also note that you don't need to publish your code to a remote repo before you can build it. But it's still recommended to follow this pattern so you'll have less work to make it work in the future if you decide to publish it. Nothing to lose here.
More in the docs: Command go: Defining a module
Also: How to Write Go Code: Code organization

Related

How do I import a project within a Go Workspace?

I have a monorepo with multiple modules within it. Some of the modules are libraries, others are entry points that will produce binaries.
Here's my workspace project:
https://github.com/alshdavid/go-workspace-example
I have my "bar" library here which I would like to make available for import by consumers outside of this mono repo.
package main
import (
"fmt"
"github.com/alshdavid/bar"
// Or maybe: "github.com/alshdavid/gotest/modules/bar"
)
func main() {
fmt.Println(bar.Bar)
}
Trying to install the package from the workspace git repo results in failure.
go get github.com/alshdavid/gotest
go get github.com/alshdavid/gotest/modules/bar
go get github.com/alshdavid/bar # worth a shot
Is there an argument I should pass to go get that instructs to to look for a module in a nested folder or should I instead set up a pipeline that pushes my nested module to its own repository?
You must be working inside a module i.e. ran: go mod init in each of your modules in your mono repo.
For example, in your case I am assuming you have module named bar and you want to import module bar inside another module e.g. foo.
A module has a go.mod file. Inside go.mod file of your foo module you can add the following:
replace github.com/alshdavid/bar => ../bar
You can read more about this here
I just needed the complete path in the go.mod file

Organize local code in packages using Go modules

I can not find a way to factor out some code from main.go into a local package when using Go modules (go version >= 1.11) outside of $GOPATH.
I am not importing any external dependencies that need to be included into go.mod, I am just trying to organize locally the source code of this Go module.
The file main.go:
package main
// this import does not work
import "./stuff"
func main() {
stuff.PrintBaz()
}
The file ./stuff/bar.go (pretending to be a local package):
package stuff
import "log"
type Bar struct {
Baz int
}
func PrintBaz() {
baz := Bar{42}
log.Printf("Bar struct: %v", baz)
}
The file go.mod (command go mod init foo):
module foo
go 1.12
When executing go run main.go:
If I import "./stuff", then I see build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff.
If I import "stuff", then I see build command-line-arguments: cannot load stuff: cannot find module providing package stuff.
If I import stuff "./stuff" with a package alias, then I see again: build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff.
I can not find a way to make local packages work with go modules.
What's wrong with the code above?
How can I import local packages into other Go code inside a project defined with Go modules (file go.mod)?
Module structure
The most common and easiest approach is:
Use a single go.mod per repository, and
Place the single go.mod file in the repository root, and
Use the repository name as the module path declared in the module line in the go.mod
(If you are using a custom import path such as me.io/mymod rather than using a VCS host based import path, then you would use the custom import path instead of the repository name in your go.mod).
For example, if your repo is github.com/my/repo, then you would place a single go.mod in the repo root, with the first line reading module github.com/my/repo. That can be created by cd'ing to the repo root and running go mod init github.com/my/repo. When working with the repo locally, the repo directory can be located wherever is convenient on your filesystem. (If you do not have a repo, see below).
Following this helps you stay on the happy path with modules, and it avoids multiple subtleties.
Russ Cox commented in #26664:
For all but power users, you probably want to adopt the usual convention that one repo = one module. It's important for long-term evolution of code storage options that a repo can contain multiple modules, but it's almost certainly not something you want to do by default.
There is much more about multi-module repositories in the "Multi-module Repositories" FAQ section on the modules wiki. Those 6 or so FAQs in that section should be read in their entirety by anyone considering veering off the recommendation above.
Arranging packages within a module
Once you have set up your go.mod, you can arrange your packages in directories however you see fit in directories underneath the directory containing the go.mod, as well as in the directory with the go.mod. Three good articles about how to arrange your code in packages:
https://rakyll.org/style-packages/
https://medium.com/#benbjohnson/standard-package-layout-7cdbc8391fc1#.ds38va3pp
https://www.goinggo.net/2017/02/design-philosophy-on-packaging.html
Those articles are classics that pre-date the introduction of modules, but the philosophies in them still apply to how to arrange your packages within a module.
Importing other packages in the same module
When importing another package with modules, you always use the full path including the module path. This is true even when importing another package in the same module. For example, if a module declared its identity in its go.mod as module github.com/my/repo, and you had this organization:
repo/
├── go.mod <<<<< Note go.mod is located in repo root
├── pkg1
│   └── pkg1.go
└── pkg2
└── pkg2.go
Then pkg1 would import its peer package as import "github.com/my/repo/pkg2". Note that you cannot use relative import paths like import "../pkg2" or import "./subpkg". (This is part of what OP hit above with import "./stuff").
Modules vs. repositories vs. packages vs. import paths
A Go module is a collection of related Go packages that are versioned together as a single unit. Modules record precise dependency requirements and create reproducible builds.
Summarizing the relationship between repositories, modules, and packages:
A repository contains one or more Go modules (most often exactly one module in the repository root).
Each module contains one or more Go packages.
Each package consists of one or more Go source files that all reside in a single directory.
Each Go source code file:
declares its own package with a package foo statement, which must be consistent for all Go files in a single package directory.
automatically has access to other Go source code in the same package, without explicitly importing its own package.
imports code from another package via an import path supplied in an import statement such as import "github.com/my/repo/pkg1". The import path always starts with the module path of that package, regardless of whether that package is in the same module or a different module.
A single module can be used to build multiple executable binaries, but the func main() {...} entry point for each binary must be in its own package main, with each package main in a distinct directory.
Local-only modules
You can create, build and run modules without ever publishing them or placing them on a VCS server.
A module is defined by a tree of Go source files with a go.mod file in the tree's root directory, so you can pick a directory on your local filesystem to serve as the root of your module and place your go.mod there. Everything described above still applies, except there does not need to be a repo.
For example:
some-directory/
├── go.mod <<<< go.mod at module root declaring 'module example.com/foo'
├── pkg1
│ └── pkg1.go
└── pkg2
└── pkg2.go
If the module path in the first line of that go.mod reads module example.com/foo, then pkg1 would import its peer package as import "example.com/foo/pkg2".
Of course, you can start with a local-only module without a repo, then later start tracking it in a local repo or publish it to a VCS server.
Even for local-only modules, it is a good idea to give the module a globally unique name, such as go mod init my.org/foo, or go mod init github.com/some/repo as if it will be published someday, even if that repo does not yet exist. (If you are in a hurry, it is possible to use a shorter module name without a dot or leading hostname component, such as go mod init temp or go mod init m, but it won’t be fetchable by the go command, and you run the risk of colliding with a current or future standard library package or otherwise seeing confusing error messages later).
If you have multiple local modules, you can point them at each other via replace directives or via the Go 1.18+ workspace feature, though those are more complex workflows than placing everything for a given project in a single module.
Next steps
If you are new to Go modules, it is worthwhile to go through the official "Create a Go Module" tutorial from the Go project. This will likely save you time overall.
If you are stuck right now with an error message related to modules or import paths, there's a very good chance the error will make much more sense after completing the tutorial.
First you have to choose a name for your project and write it to go.mod file. This name belongs to root directory of the project. Each new package you create must be located inside its own subdirectory and its name should match directory name.
go.mod:
module myprojectname
or (preferred way, see #thepudd's answer for details)
module github.com/myname/myproject
Then import your project's packages like:
import myprojectname/stuff
or
import github.com/myname/myproject/stuff
Files of package stuff should be located inside project's stuff directory. You name these files as you like.
Also it's possible to create deeper project structure. For instance, you decided to separate source code files from other ones (like app configs, docker files, static files, etc...). Let's move stuff directory inside pkg, every go file inside pkg/stuff still have stuff package name. To import stuff package just write:
import myprojectname/pkg/stuff
Nothing stops you from creating more levels in the hierarchy like github.com/myuser/myproject/pkg/db/provider/postgresql, where:
github.com/myuser/myproject - project name.
postgresql - package name.
pkg/db/provider/postgresql - path to the package relative to project's root.
You can read more about go modules here: https://github.com/golang/go/wiki/Modules
Check out this repository to get useful information about various patterns used in project organizing: https://github.com/golang-standards/project-layout If you go inside pkg directory you will find out which open source projects use pkg directory in their structure.

How to share a local module in Go 1.11+ for Golang using monolithic repo architecture outside GOPATH [duplicate]

I've created a library as the module for personal use outside of "GOPATH" in "database" folder with this command "go mod init database," and I don't know:
How to use/import this module in another module?
OS: Windows 7, Go: v1.11
The easiest and working out-of-the-box solution is to put your database package / module into a VCS (e.g. github.com), so other packages (inside other modules) can simply refer to it by importing it like:
import "github.com/someone/database"
If you do so, you don't even have to fiddle with the go.mod files manually, everything will be taken care of by the go tool: it will automatically recognize and resolve this dependency, download and install the required package, and will also update go.mod automatically.
Staying entirely on local disk
If you don't want to use a VCS (e.g. you're just experimenting or you haven't decided what to use yet), then you can still do it. The how is detailed in the official Go Wiki: Can I work entirely outside of VCS on my local filesystem?
So you created a database folder outside of GOPATH, and you created a module in it. And you created another module, let's call it main, and you want to use this database package.
What you must do is:
go.mod of your main module must list the database package as a "requirement". Give a temporary VCS name to your database package:
require (
example.com/me/database v0.0.0
)
You must tell the go tool where this package is located, because the full package name we used is just a temporary / fantasy name. Use the replace directive to make this database package point to a folder on your local disk; you may use absolute and relative paths:
replace example.com/me/database => ../database
And that's all.
Working example
Let's see a working example. Let's create a pretty module. Create a pretty folder with 2 files in it:
pretty.go:
package pretty
import "fmt"
func Pretty(v ...interface{}) {
fmt.Println(v...)
}
go.mod (can be created by running go mod init pretty):
module pretty
Now let's create another, main module. Let's create a folder osinf (it may be whatever) next to the pretty folder. 2 files in it:
osinf.go (note we intend to use our pretty package / module, we import it by "example.com/me/pretty"):
package main
import "example.com/me/pretty"
func main() {
pretty.Pretty("hi")
pretty.Pretty([]int{1, 3, 5})
}
go.mod:
module main
require example.com/me/pretty v0.0.0
replace example.com/me/pretty => ../pretty
And that's all.
Running go run osinf.go in the osinf folder, the output is:
hi
[1 3 5]
Run:
go mod init yellow
Then create a file yellow.go:
package yellow
func Mix(s string) string {
return s + "Yellow"
}
Then create a file orange/orange.go:
package main
import "yellow"
func main() {
s := yellow.Mix("Red")
println(s)
}
Then build:
go build
https://golang.org/doc/code.html

How do I resolve "cannot find module for path X" importing a local Go module?

In my Go project, I want to break out some generic functionality into a Go module, separate from the main project. I'm doing this outside of GOPATH in keeping with go's future. I don't want to publish the module on GitHub or anywhere else.
All my attempts to import this module into the main project result in:
cannot find module for path X
I've run go mod init X in the module's folder. The contents of its go.mod file is:
module X
Building or installing this module seems to do nothing. I've found no sign of it in $GOPATH/pgk/mod.
I've tried a variety of import statements:
import "X"
import "../x" (relative path to the module directory)
import "../x/X" (path to the directory + module name)
Help!
So you wrote a Go "library" module X which:
you don't want to publish on GitHub or elsewhere
you want to import and use in your project (the "main" module).
Use a replace directive along with require
In your main module's go.mod, add the following lines:
require "X" v0.0.0
replace "X" v0.0.0 => "{local path to the X module}"
The path should point to the root directory of X. It can be absolute or relative.
To import package util from module X:
import "X/util"
(You don't import modules. You import packages from modules.)
Explanation
Go's module functionality is designed for publicly published modules. Normally, a module's name is both its unique identifier and the path to its public repo. When your go.mod declares a module dependency with the require directive, Go will automatically find and retrieve the specified version of the module at that path.
If, for example, your go.mod file contains require github.com/some/dependency v1.2.3, Go will retrieve the module from GitHub at that path. But if it contains require X v0.0.0, "X" isn't an actual path and you will get the error cannot find module for path X.
The replace directive allows you to specify a replacement path for a given module identifier and version. There are many reasons you'd want to do this, such as to test changes to a module before pushing them to the public repo. But you can also use it to bind a module identifier to local code you don't ever intend to publish.
More details in the Go Modules documentation:
Can I work entirely outside of VCS on my local filesystem?
When should I use the replace directive?
Hope this helps.
If you don't want to use Go modules, you don't need to. As of Go v1.13, by default, go modules are used. Therefore, you need to tell explicitly if you don't want to do this.
Example:
main.go:
package main
import (
"fmt"
"./pakk"
)
func main() {
fmt.Println("Hello" + pakk.World())
}
pakk/pakk.go:
package pakk
func World() string {
return " world"
}
In this case, running go run main.go will output
build command-line-arguments: cannot find module for path .../pakk
but running
GO111MODULE=off go run main.go
will output
Hello world
Spent 4 days figuring this out. Very disapointed, but the way to import ./X
is as following:
first issue this magic command:
go mod init poop/strawberry/monkey
then you can EASILLY import your ./X folder:
import (
"poop/strawberry/monkey/X"
)
Folder structure:
./X/X.go
./main.go
./go.mod
contents of go.mod:
module poop/strawberry/monkey
this is the awesome solution from go module creators
https://go.dev/ref/mod#go-mod-init
module path: A path that identifies a module and acts as a prefix for package import paths within the module. For example, "golang.org/x/net"
go mod init api.com
// "api.com" name your app , it's alike swift 's bundle identifier , your can also "whatever.youlike"
myExample
Error ? Go cannot resolve the path to your modules, this is probably from misconfiguration or (not configuring) of the "go.mod" file used for project dependency tracking.
Solution lets assume your project folder looks like below;
/
|-- folderOne/
|-- folderTwo/
|-- folderThree/
|-- main.go
And the main.go script imports the modules folderOne,folderTwo and folderFour's script (folderfour.go) imports the module folderThree.
folderOne:
execute in the commandline:
go mod init github.com/../folderOne (i.e path from github.com folder to folderOnes)
The go mod init command creates a go.mod file to track your code's dependencies
folderTwo:
execute in the commandline:
go mod init github.com/../folderTwo (i.e path from github.com folder to folderTwos)
The go mod init command creates a go.mod file to track your code's dependencies
folderThree:
execute in the commandline:
go mod init github.com/../folderThree (i.e path from github.com folder to folderThrees)
The go mod init command creates a go.mod file to track your code's dependencies
folderFour:
execute in the commandline:
go mod init github.com/../folderThree (i.e path from github.com folder to folderFour)
Go to the folderFours script and import the module folderThree i.e
import "github.com/../folderThree"
in folderfours commandline:
$ go mod edit -replace github.com/{pathto}/folderThree=./folderThree**
then execute: go mod tidy
in your projects root folder execute the command: go mod init github.com/../ProjectRootDirectory (i.e path from github.com folder to ProjectRootDirectory)
then to import the modules, i.e folderThree, folderTwo, folderOne
execute the following at the projects root folder(ie folder with main.go)
$ go mod edit -replace github.com/{pathto}/folderOne=./folderOne
$ go mod edit -replace github.com/{pathto}/folderTwo=./folderTwo
$ go mod edit -replace github.com/{pathto}/folderFour=./folderFour
then execute;
$ go mod tidy
and then
$ go run main.go

golang modules and local packages

I'm trying to understand how to organize my golang project using go1.11 modules. I tried several options, but none of them worked.
I have some code in the main package under the application folder and a local package that the main package uses.
$GOPATH
+ src
+ application/
+ main/
+ main.go
+ otherFileUnderMainPackage.go
+ aLocalPackage/
+ someCode.go
+ someCode_test.go
+ someMoreCode.go
+ someMoreCode_test.go
Files in the main package, imports ../aLocalPackage. When I compile by go build main/*.go it's working.
Then, I ran go mod init application: V.0.9.9 and got the go.mod file, but the build always fails. I always get error about not finding the local package: build application:V0.9.9/main: cannot find module for path _/.../src/application/aLocalPackage. I also tried to place the local package right under src/, place it under main/ etc. but none of these methods worked for me.
What is the way to use modules and local packages?
Thanks.
Relative import paths are not supported in module mode. You will need to update your import statements to use a full (absolute) import path.
You should also choose a module name other than application. Your module path should generally begin with a URL prefix that you control — either your own domain name, or a unique path such as github.com/$USER/$REPO.
I had some problems working with local packages myself.
There are two tricks to make it work:
you run "go build" in the package directory
This compiles the package and places it in the build cache.
This link about code organisation in go explains more.
You can identify where the cache is using:
>go env GOCACHE
/home/<user>/.cache/go-build
Import using a path relative to the project
I puzzled loads over what the correct import path was and finally discovered that go doc or go list will tell you.
>go doc
package docs // import "tools/src/hello/docs"
>go list
tools/src/hello/docs
For example. I have a hello world API project and was using swaggo to generate documentation which it does in a docs sub-directory.
To use it I add an import:
_ "tools/src/hello/docs"
For my case the _ is important as docs is not used directly but we its init() function to be invoked.
Now in hello/main.go I can add "tools/src/hello/docs" and it will import the correct package.
The path is relative to the location of go.mod if you have one.
I have tools/ here as I have a go.mod declaring "modules tools".
Modules are a different kettle of fish - see https://github.com/golang/go/wiki/Modules.
Recent versions of go (1.11 and later) can create a go.mod file which you may use to fix the version of a module that is used and avoid go's crazy default behaviour of just downloading the latest version of any package you import.
I have written a blogpost on how to start your first Go project using modules.
https://marcofranssen.nl/start-on-your-first-golang-project/
In general it boils down to just create a new folder somewhere on your system (doesn't have to be in GOPATH).
mkdir my-project
cd my-project
go mod init github.com/you-user/my-project
This will create the go.mod file. Now you can simply create your project layout and start building whatever you like.
Maybe one of my other blogs can inspire you a bit more on how to do things.
https://marcofranssen.nl/categories/software-development/golang/

Resources