I have following project structure
./
lib/ shared library
cmd/
cli/
main.go
srv/
main.go
in the main.go i have
package main
import "fmt"
func main() {
fmt.Println("cli")
}
from root folder i run go build ./..., in a hope that cli and srv binaries would be created in a root folder, but nothing happens
but running go build ./cmd/cli does produce a cli binary in root folder
what is wrong?
As of Go 1.13, go build will output multiple executables if you set the -o flag explicitly to a directory. So, for example, mkdir -p ./bin && go build -o ./bin ./... will build all executables matching ./... and output them to the directory ./bin.
Related
Using Go version go1.17.1 linux/amd64 on my CentOS 7. GOPATH and GOROOT are set in my .bashrc in the order:
export GOPATH="${HOME}/.go"
export GOROOT="/usr/local/go"
export PATH="$PATH:${GOPATH}/bin:${GOROOT}/bin"
Got my project in /home/wsb/_projects/local/parlance:
[wsb#localhost local]$ pwd
/home/wsb/_projects/local
[wsb#localhost local]$ tree
.
└── parlance/
└── main.go
└── utils.go
From the terminal, using go get stores src in /home/wsb/.go/pkg/mod/cache... folder
[wsb#localhost parlance]$ go get -v -u github.com/gorilla/mux
go: downloading github.com/gorilla/mux v1.8.0
github.com/gorilla/mux
[wsb#localhost parlance]$ go build main.go
main.go:3:8: no required module provides package github.com/gin-gonic/gin: go.mod file not found in current directory or any parent directory; see 'go help modules'
[wsb#localhost parlance]$
[root#localhost /]# find -iname gin
./home/wsb/.go/pkg/mod/cache/download/github.com/gin-gonic/gin
Why would it throw error on build?
Using go mod is the key here for managing packages for any particular projects.
go mod is used for installing and tracking external packages outside of packages in GOPATH.
From within existing project root directory parlance we initialize go mod using:
[wsb#localhost parlance]$ go mod parlance
It creates two files within the project root directory: go.mod and go.sum.
Now we can go get any module we will use specifically for our project.
go get github.com/gin-gonic/gin
go get github.com/gofiber/fiber/v2
This creates external package requirement details in go.mod and their respective checksum in go.sum file.
Finally, we can build/run our package like
go build main.go
go run main.go
Take a look at this directory structure:
/root
/bar
go.mod
go.sum
main.go
main_test.go
/foo
go.mod
go.sum
main.go
main_test.go
I'd like to debug root/foo/main.go using the delve debugger from the command line. I've tried building the binary using go build, and then using dlv debug <binary> with errors like:
can't load package: package foo is not in GOROOT (/usr/local/opt/go/libexec/src/foo)
exit status 1
Any thoughts?
Your root has two different modules in it, foo and bar. You can't use go build from root to build them, because go build doesn't support nested or multiple modules. You have to run it from the directory go.mod is in, or any of its child directories.
Since Delve simply calls go build for you, the same applies with dlv debug. Try to cd into foo first, and then run dlv debug.
Following is how the source files are organized
✘-1 ~/Go/src/github.com/krmahadevan/packages
18:24 $ tree .
.
├── sample_main.go
└── sample_one.go
0 directories, 2 files
Here's how the source code looks like:
sample_one.go
package main
var data map[string]string
func init() {
data = make(map[string]string, 0)
}
sample_main.go
package main
import "fmt"
func main() {
data["foo"] = "bar"
fmt.Println(data)
}
Now when I attempt at running sample_main.go I get errors stating that data is undefined.
18:24 $ go run sample_main.go
# command-line-arguments
./sample_main.go:6:2: undefined: data
./sample_main.go:7:14: undefined: data
✘-2 ~/Go/src/github.com/krmahadevan/packages
But when I build the code into a binary and then execute it, it runs fine.
✔ ~/Go/src/github.com/krmahadevan/packages
18:27 $ go build
✔ ~/Go/src/github.com/krmahadevan/packages
18:28 $ ./packages
map[foo:bar]
✔ ~/Go/src/github.com/krmahadevan/packages
I would like to understand why is this behavior ?
Environment:
18:31 $ go version
go version go1.11.4 darwin/amd64
The closest I found was this post : Golang : command-line-arguments undefined: variable
But this post talks about scoped variables that are defined in main.
But my problem statement involves variables defined in another go file and accessed in the main method.
To understand why, read the go command documentation:
Command go
Compile and run Go program
Usage:
go run [build flags] [-exec xprog] package [arguments...]
Run compiles and runs the named main Go package. Typically the package
is specified as a list of .go source files, but it may also be an
import path, file system path, or pattern matching a single known
package, as in 'go run .' or 'go run my/cmd'.
Compile packages and dependencies
Usage:
go build [-o output] [-i] [build flags] [packages]
Build compiles the packages named by the import paths, along with
their dependencies, but it does not install the results.
If the arguments to build are a list of .go files, build treats them
as a list of source files specifying a single package.
For more about specifying packages, see 'go help packages'. For more
about where packages and binaries are installed, run 'go help gopath'.
go run: Typically the package is specified as a list of .go source files.
For your go run example, list the files:
go run sample_main.go sample_one.go
To fix it, just run the following command:
Windows: go run * or go build *
Unix: go run . or go build .
You are going to run it inside the folder of the files you want to use.
I have the error:
go install: no install location for directory /Users/xwilly/Dropbox/go/project/src outside GOPATH
I'm using go version 1.1 on OS X.
I can build & run but can't install packages.
My environment:
GOPATH=/Users/xwilly/Dropbox/go/project
PATH=/Library/Frameworks/Python.framework/Versions/2.7/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/go/bin:/Users/xwilly/Dropbox/go/project/bin
Project tree:
/Users/xwilly/Dropbox/go/project
bin
pkg
src
I can build without error:
..:src xwilly$ go build test.go
..:src xwilly$ go install test.go
go install: no install location for directory /Users/xwilly/Dropbox/go/project/src outside GOPATH
Here is a simple example:
xwilly$ cat test.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Bonjour")
}
xwilly$ go run test.go
Bonjour
xwilly$ go install test.go
go install: no install location for directory /Users/xwilly/Dropbox/go/project/src/learning outside GOPATH
Command go
GOPATH environment variable
Each directory listed in GOPATH must have a prescribed structure:
The src/ directory holds source code. The path below 'src' determines
the import path or executable name.
The pkg/ directory holds installed package objects. As in the Go tree,
each target operating system and architecture pair has its own
subdirectory of pkg (pkg/GOOS_GOARCH).
If DIR is a directory listed in the GOPATH, a package with source in
DIR/src/foo/bar can be imported as "foo/bar" and has its compiled form
installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
The bin/ directory holds compiled commands. Each command is named for
its source directory, but only the final element, not the entire path.
That is, the command with source in DIR/src/foo/quux is installed into
DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped so that you
can add DIR/bin to your PATH to get at the installed commands. If the
GOBIN environment variable is set, commands are installed to the
directory it names instead of DIR/bin.
Here's an example directory layout:
GOPATH=/home/user/gocode
/home/user/gocode/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)
Your directory structure is wrong. You are trying to install a command (package main). It should be in a source directory named after your command. See the quux command above.
In your case, assume your command is going to be named billy.
$ mkdir -p /Users/xwilly/Dropbox/go/project/src/billy
which is inside your GOPATH. Move your test.go file to this directory. Run
$ go install billy
The command billy should, unless you have set GOBIN, be installed in the
/Users/xwilly/Dropbox/go/project/bin
directory inside your GOPATH, which should be in your PATH.
Where should I put my package so that it can be imported by another package?
$ tree
.
├── main.go
└── src
└── test.go
1 directory, 2 files
$ cat src/test.go
package test
$ cat main.go
package main
import "test"
$ go build main.go
main.go:3:8: import "test": cannot find package
Set your GOPATH. Put your package foo source(s) in GOPATH/src/optional-whatever/foo/*.go and use it in code as
import "optional-whatever/foo"
You don't need to explicitly install foo, the go tool is a build tool, it will do that automagically for you whenever necessary.
There are a few things that need to happen. You must install the "test" package first:
$ export GOPATH=$(pwd) # Assumes a bourne shell (not csh)
$ mkdir src/test
$ mv src/test.go src/test/test.go
$ mkdir pkg # go install will put packages here
$ go install test # build the package and put it in $GOPATH/pkg
$ go build main.go
Note that it is not necessary to create pkg, as go install will do that for you.
Once you've installed the test package (generally a bad name, BTW) go build main.go should now give different errors (eg, "imported and not used")
maybe, you can put the test.go file in the same directory with the main.go, and
in test.go, it uses something like this:
import "./test"