Golang: Building and running with new directory structure - go

Brushing up on my golang, I see that there is a new recommended directory structure for go projects: We should be emitting the "src" directory from our project.
Here is an example of such a project: https://github.com/golang-standards/project-layout , and I have also seen this mentioned in several recent articles.
Until now, I have created a package under /myproject/src/mypackage. Then, to run my project I would add /myproject to $GOPATH.
My question: If I use the new directory structure, how would I go about building and running my project? I could "hack" it by creating a symlink into a "src" directory... But that seems rather "dirty" (If I was going to do that, I could've just used "src" to begin with) .
I would appreciate if someone could point out the build and run commands for a project arranged in the structure mentioned above.
EDIT based on comments: This question is not about whether I want to use "src" or not. I definitely do want to embrace this new project structure. It's just that I cannot find instructions on how to build and run a project with such a directory structure. For example: How would I reference the files in the pkg directory if it's not in my "$GOPATH/myproject/src"?

Related

should src folder be created in golang go1.17

I am starting off with golang according to some document it mentions $GOPATH default should have bin pkg src directories.
When a I do go get github.com/astaxie/beedb there no src folder created and the source goes and sits in $GOPATH/pkg//mod/github.com/astaxie/beedb#v0.0.0-20141221130223-1732292dfde4/
according to documentation the it should be in src folder
I am using golang go1.17. Has something changed in newer versions or am I refering old doc.
you don't need to create src folder under $GOPATH
With Go modules, Go projects are no longer confined to $GOPATH
Don't confuse the project level /src directory with the /src directory Go used to use for its workspaces, but please note
"Since Go 1.14, module support is considered ready for production use, and all users are encouraged to migrate to modules from other dependency management systems "
please check below links
https://github.com/golang/go/wiki/Modules
There is no need to manually create the sub-folders in $GOPATH. When you run go get, go will handle everything for you. So if there is no src folder, you can just leave it.
The src folder was basically for package management before Go Modules (enabled by default since go 1.13). You don't really need this now.

Confused on how to build a go project from source

I'm trying to build the Ethereum node Geth: https://github.com/ethereum/go-ethereum
I cloned the project in my src folder ( in a folder called geth, should not metter, right? ) and when I try to run/compile does not find:
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/cmd/utils"
and currently these file exists, as part of the project I'm trying to compile, so I don't actually understand why is referring the repository on line, and, in any case, why it does not work
You must clone the geth source in the exact folder in your GOPATH, actual path should be GOPATH/src/github.com/ethereum/go-ethereum.

Modifying an imported library in Go

My Problem
Elastic Beats is an open source project for log shippers written in Go. It features several log outputs, including console, Elasticsearch and Redis. I would like to add an output of my own - to AWS Kinesis.
I have cloned the repo to ~/github/beats, and tried building it:
$ cd filebeat; go build main.go
However, it failed due to a missing library which is a part of the project:
main.go:6:2: cannot find package "github.com/elastic/beats/filebeat/cmd" in any of:
/usr/local/go/src/github.com/elastic/beats/filebeat/cmd (from $GOROOT)
/Users/adam/go/src/github.com/elastic/beats/filebeat/cmd (from $GOPATH)
A directory of the project is dependent on a package from the same repo, but instead of looking one directory up the hierarchy it looks in the GOPATH.
So, go get github.com/elastic/beats/filebeat/cmd fetched the code, and now go build main.go works. Changing the code in my GOPATH is reflected in these builds.
This leaves me with an structural inconvenience. Some of my code is at a working directory, and some of it is at my GOPATH and included by the code in my working directory.
I would like to have all my code in a single directory for various reasons, not the least being keeping everything under version control.
What Have I Tried
Mostly searching for the problem. I am quite new to Go, so I might have missed the correct terminology.
My Question
What is the right way to edit the code of an imported library in Go?
One of the recommended ways to work with other's packages is:
Get the sources of the original package:
go get github.com/elastic/beats
As a result you will clone project's git repository to the folder
$GOPATH/src/github.com/elastic/beats
Make some fixes, compile code, fix, compile... When you make go install package will be compiled and installed to your system. When you need merge updates from original repository you can git pull them.
Everything is OK. What's next? How to share your work with others?
Fork project on github, suppose it will be github.com/username/beats
Add this fork as another remote mycopy (or any other name you like) to your local repository
git remote add mycopy git://github.com/username/beats.git
When all is done you can push updated sources to your repo on github
git push mycopy
and then open a pull-request to original sources. This way you can share your work with others. And keep your changes in sync with mainstream.
Previous answers to this question are obsolete when developing projects that using Go Modules.
For projects that using Go Modules, one may use the following command to replace an imported library(eg. example.com/imported/module) with a local module(eg. ./local/module):
go mod edit -replace=example.com/imported/module=./local/module
Or by adding the following line into the go.mod file:
replace example.com/imported/module => ./local/module
Reference Docs: https://golang.org/doc/modules/managing-dependencies#unpublished
A project working copy should be checked out into $GOPATH/src/package/import/path - for example, this project should be checked out into /Users/adam/go/src/github.com/elastic/beats. With the project in the correct location, the go tooling will be able to operate on it normally; otherwise, it will not be able to resolve imports correctly. See go help gopath for more info.

Path that is working with go run is not working with go install/calling the executable from bin

I'm starting to experiment with Go and I'm facing an issue that (I think) doesn't exist in languages that use a virtual machine.
I have a src/test/main.go file that references my templates inside src/test/views/ folder.
When I use go run main.go it runs but when do go install and then inside my bin folder run the executable (./test) I get an error:
views/edit.html: no such file or directory
So, how does Go compiles my project (file/folder structure related) and how to use paths in a way that allows me to use either go run and go install/executable?
If you specify a relative path in your code, as in views/edit.html it will also be looked up relative to the binary location. You need to either make the path absolute, or use some logic to determine where your templates will be located.
Another option would be to use https://github.com/jteeuwen/go-bindata or https://github.com/elazarl/go-bindata-assetfs that will save you the hassle.

Move main out of the repository root in go

I am creating a project in go. Since there is already a lot of things at the root of the repository of the project (doc, README.md...), I want all the source code to go in a folder src, and all the test code in a folder named test :
\go
\src
\github.com
\user
\my_project
\src
main.go
some_func.go
\test
test_main.go
test_some_func.go
\doc
README.md
But I have two issues :
The build command is not working while I am in the my_project folder. I have to go in the my_project/src to successfully run build. I want to do it from the my_project folder. How to inforce go to understand that the source for my_project is in the src code ?
Then the executable produced by the go install command is named src. How to change the name of that executable ?
I want all the source code to go in a folder src, and all the test code in a folder named test :
Go has a way that it organizes source code. Do not fight this. It is how the system works. Organize your code the way Go wants you to. Do not try to force Go to work the way you have learned working in some other language. Every language has its own ways of doing things. None of them are "correct." Like Java, Go has very specific ideas of what you're supposed to do. Do it that way. (This isn't an argument about whether Go is "right" or Go is "wrong." Go is Go, and it does things in the Go way.)
In particular, you should not create another "src" directory. There is already a "src" directory at the top of the "go" tree. If you create another, redundant, "src" directory, then the package name for your project is "github.com/user/my_project/src" which is likely not what you want.
To make the executable be named what you want, put it in a directory named what you want (probably "my_project"). Put test files with the files they test. This is how go works.
So your tree should look like:
\go
\src
\github.com
\user
\my_project
main.go
some_func.go
main_test.go
some_func_test.go
\doc
README.md
Attempts to do something other than this is going to blow up over and over again, and questions of "how do I make the build system do this other thing" will continually return "put your code in the way the build system expects."
For details on what Go expects, and how you should organize your code, see GOPATH environment variable in the Command Go documentation. Once you've built your system this way for a while, you will start to see where you can deviate from it (like creating other directories for test utilities, but not test cases). Don't start deviating until you've tried it the standard Go way.

Resources