Correct directory structure for a Go Project? - go

I'm relatively new to Go and I've recently created a project that's going up on GitHub. I've tried to follow guides but there's a pressing question of why my binaries end up in src/?
My layout is like this:
ssm/ - Name of project
LICENSE
README.md
src/ - Source Code
files.go - All my source code is here.
src - The compiled binary ends up here
bin/ - Binaries
I set my $GOPATH to ~/Documents/Programming/Go/. From my gopath, I can't type go build ssm because it cannot find package. If I cd into the directory, it complains it can't load package: package .: no Go source files.
I have to actually go into src and compile there, which means the binary isn't in bin/.
What am I doing wrong?

See https://code.google.com/p/go-wiki/wiki/GithubCodeLayout
To be compatible with go get, your project's package name needs to be fully-qualified under the github.com domain:
$GOPATH/
src/github.com/<user>/ssm/
.git
LICENSE
README.md
files.go
bin/
Note that the base of the git repository (.git) is not the same as the $GOPATH.
Also, go build <package> will output a compiled executable to the current directory. If you want the exe to go to bin/, use go install <package> instead.

Your go code you can kept in a workspace. A workspace contains many source files (git, hg, svm, etc.). The Go tool understand the layout. We don't require Makefile or build.xml here. The basic directory layout is everything. If in any case if you are going to change the file layout, accordingly you need to change the build.
This is the general structure you can follow,
$GOPATH/
src/
github.com/username/repo/
mypkg/
mysrc1.go
mysrc2.go
cmd/mycmd/
main.go
bin/
mycmd
And, this is the standard workspace
$GOPATH/
bin/fixhub # installed binary
pkg/darwin_amd64/ # compiled archives
code.google.com/p/goauth2/oauth.a
github.com/...
src/ # source repositories
code.google.com/p/goauth2/
.hg
oauth # used by package go-github
...
github.com/
golang/lint/... # used by package fixhub
.git
google/go-github/... # used by package fixhub
.git
dsymonds/fixhub/
.git
client.go
cmd/fixhub/fixhub.go # package main
go get fetch many repositories whereas go install builds a binary out of them. It's convenient and easy to go for go development quickly. And, everyone in the go community follows the same. This puts src, bin and pkg into the home directory. And, $HOME/bin is already in our path before creating our workspace.

Related

Not in any GOPATH while using dep init

I'm trying to use godep to install my dependencies but I can't seem to get it to work. When I run GODEP init, I get the following error
determineProjectRoot: /home/cjds/development/core/data-service not in any $GOPATH
But my GOPATH definitely contains that path. This is my whole go path
/home/cjds/development/core/data-service
go install causes the following error, which may be the root of the problem:
no buildable Go source files in /home/cjds/development/core/data-service
The folder structure however has a src folder, and then a main folder and then my whole Go project
-/home/cjds/development/core/data-service/src/main/my-go-files.go
Your GOPATH points to a root directory containing bin, pkg, and src subdirectories, with project source under src. Tools like godep and go install expect to operate on source, not on your entire GOPATH, so must be run on some path under $GOPATH/src.

Go build multiple/nested packages?

I just started writing Go today (so 0 experience), and wonder if Go supports any form of "building all source files" like what mvn install does.
My project structure is
src
`-github.com
`-myproject
|- package1
| `- main.go
`- package2
|- lib1_used_by_main.go
`- lib2_used_by_main.go
When I do
cd src/github.com/myproject
go build
this fails with no buildable Go source files in src/github.com/myproject, which is kind of right, because all source files are in subpackages.
Is there a command to build all subpackages, without listing each of them explicitly?
After you cd to the base directory, use go build ./... Note that there are 3 periods as it is an ellipsis. This will recursively build all subdirectories. Of course you can always do go build path/to/my/base/... from wherever without needing to cd to the directory.
This is very useful for those who use an IDE that relies on the go/pkg directory, such as SublimeText3 with GoSublime. Making changes to a dependency package won't update the autocompletes until you build the package, which places it in the go/pkg directory.
My own projects are broken into a multiple package structure, so I frequently have to go build ./... to update my autocompletion.

Building Golang project properly

I have a project structure that looks like so:
I was planning on just using a shell script (build.sh) to set GOPATH and build the project.
I am not sure how to build a Golang project properly, my short term goal is to just to build the packages in the src directory and put the binaries into the bin directory.
I am not sure what go build command can do that, I have tried a few things.
So first my question is - is this a reasonable project structure and second, how can I compile my src directory to bin?
What I have gives me the following error:
can't load package: package .: no buildable Go source files in /home/oleg/WebstormProjects/oresoftware/stack-server
So I believe I need to tell Go to look in the src directory, because Go is only looking for .go files in the project root, but I am not sure how to do that.
If it matters, the main.go file has a package name of "main".
GOPATH=$PROJECT_DIR && cd $PROJECT_DIR && go install main
Also move your main.go file into src/main/main.go.
This will produce a bin/main executable.
If you have multiple executables you wanna build, you have to put each main.go file into a separate folder/package. The name of the generated executable is taken from the directory name the file is inside. The package name of the main.go files must always be main if it should create a binary.
To compile multiple executables you have to use:
GOPATH=$PROJECT_DIR && cd $PROJECT_DIR && go install ...
The ... matches all folders/packages.

go ignoring vendor directory

Everything I read about the vendor directory gives me the understanding that if I have a directory:
$GOPATH/src/vendor
And put my dependencies in there (I am using godeps), when doing go run, go should check in that directory first.
If I run my code in a Docker image I have, this works fine. However now that I try to run the same code on my Windows machine, go simply ignores the vendor/ directory, and fails to find the dependencies.
What am I doing wrong?
main.go:7:2: cannot find package "gopkg.in/alecthomas/kingpin.v2" in any of:
C:\Go\src\gopkg.in\alecthomas\kingpin.v2 (from $GOROOT)
C:\Users\js\dev\my_project\rest\src\gopkg.in\alecthomas\kingpin.v2 (from $GOPATH)
C:\Users\js\dev\go\src\gopkg.in\alecthomas\kingpin.v2
Is the output when I try to do:
go run main.go
A directory vendor/ exists in this directory.
go version go1.7 windows/amd64
The exact commands I run (in windows cmd.exe)
> cd C:\Users\js\dev\my_project\rest\
> set GOPATH=C:\Users\js\dev\my_project\rest\;c:\Users\js\dev\go
> cd src
> dir
...
2016-09-01 23:20 2 923 main.go
...
2016-09-03 01:27 <DIR> vendor
> go run main.go
The reason this did not work is because you are not supposed to put any code directly into the $GOPATH/src/ directory.
The solution is to put your project into a sub-directory like so:
$GOPATH/src/app/*.go
Seems your GOPATH is incorrect?
The GOPATH should specify the location of your workspace i.e. directory containing src, pkg and bin directories at its root.
Try doing
set GOPATH=C:\Users\js\dev\my_project\rest\;c:\Users\js\dev\go
More details at: https://golang.org/doc/code.html
The first thing to understand is that godep save is simply copying dependencies from your $GOPATH to a vendor directory inside your project.
You will have to go get your dependencies first. After you have them in $GOPATH, you can do a godep save to copy the current version to your project, and be assured that even if the version in $GOPATH changes, you will have a fixed version in your project until you explicitly change it via godep.
So, if I have a $GOPATH of /home/me/go_workspace, and a project called $GOPATH/src/github.com/project_x with a dependency of github.com/you/xyz, then I would do go get github.com/you/xyz, and godep save from within my project directory. This would create a vendor folder with the dependency at its current commit inside.

What does go install do?

The docs say nothing about what build vs install does
My expectation was that it's like make install; i.e. it takes the compiled stuff and puts in its final location (/usr/local/bin/my_new_toy or whatever) but it seems that it puts things in GOROOT/bin
Can I tell go to do a make install - i.e. put things elsewhere? Or do I just write a makefile (please tell me no)?
go build vs go install:
go build just compiles the executable file and moves it to the destination.
go install does a little bit more. It moves the executable file to
$GOPATH/bin and caches all non-main packages which are imported to
$GOPATH/pkg. The cache will be used during the next compilation provided the
source did not change yet.
A package tree after go build and go install:
.
├── bin
│ └── hello # by go install
└── src
└── hello
├── hello # by go build
└── hello.go
More detailed information.
If you want binary files to go to a specific location, you can use the environment variable GOBIN :
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.
Source : http://golang.org/cmd/go/#hdr-GOPATH_environment_variable
GOBIN=/usr/local/bin/ go install
If you want per-project bin/ directory then you can simply append your project path to GOPATH, however you must have your code under $project-path/src/ and go install will put all the binaries in $project-path/bin.
export GOPATH=/dir1:/dir2:/dir3
If GOBIN is not set, binaries from /dir1/src end up in /dir1/bin,
binaries from /dir2/src end up in /dir2/bin, and so on (and binaries
from $GOROOT/src end up in $GOROOT/bin).
Source : https://groups.google.com/forum/#!topic/golang-nuts/-mN8R_Fx-7M
And you can also just use (thanks JimB):
go build -o /path/binary-name

Resources