How to change default path to store executable in Go compiler? - go

In Go compiler, when I do "go run", executable file is stored to a temporary location. How to change this path to store the file in current working directory? I am using windows 7 64bit machine.

If you want to do something with the binary beyond just running it once, you should be using go build, not go run. go build will put the binary in the current working directory.

I agree with #Adrian and #Saleem, however, for interest sake, you can override the location (somewhat) by changing the location of your environment variable TEMP (or TMPDIR on OSX or Linux). This will still create a temporary directory in whatever directory you specify, in which the working files will be placed. Keep in mind that as Adrian and Saleem say, go run is intended for temporary runs.
And of course #JimB beat me to it with his comment which is really the essence of what I'm saying here.

Agree with previous answers. go install saves binary file into GOBIN folder. So you may change it to have a specific location. However, I don't suggest to do it, because you can always build into specific folder using -o option of go build:
go build -o /usr/bin/app main.go

The folder used by Go to store the temporary executable can be changed by setting the GOTMPDIR environment variable.
More info here: https://stackoverflow.com/a/71197493/1057961

Related

"go get" command not generating the bin folder when it is run in a shell script

I have installed go package. When I go to the instance(VM) and run the command
go get github.com/linkedin/Burrow from a terminal/cmd it is downloading both "src" & "bin" folder under user home directory. But when I run the same command by setting GOPATH in a shell script, it is only downloading the "src" folder but not generating "bin" folder.
SOURCE_DIR="/opt/burrow"
export GOPATH=$SOURCE_DIR/go
go get $BURROW_REPO
Am I missing anything?
Use go install command (Compile and install packages and dependencies).
That command download src to $GOPATH and build it to $GOBIN.
GOBIN may not be set at the moment.
You can check by go env GOBIN. if its empty so you must set with export GOBIN=$(go env GOPATH)/bin
Also, for calling binary files from your terminal, you need to use go install command. This will create related bin file under GOBIN path.
There's a lot going on here.
The first point of your confusion is that go get does not download neither "src" nor "bin": Go packages are always contain only source code, and they typically does not contain the "src" directory in their file and directory hierarchies.
Instead, these directories are artefacts of the the Go toolchain.
The second point of confusion is that since Go 1.8, the Go toolchain uses a fallback value for the GOPATH environment variable if that is not set, and on Unix-like systems it defaults to the directory named "go" under the "home" directory of the user executing the go command.
If this directory is missing, the toolchain will create it.
Hence my stab at your problem is that you have some sort of permissions problem: when GOPATH is unset, "$HOME/go" is used — with whatever value $HOME expands to for the current user; when you set GOPATH by hand, something prevents creation of the "bin" directory under $GOPATH.
There's another possibility: you also set the GOBIN environment variable, which, when set, overrides the usual location used to install binaries built by go install (and go get).
You might study the output of go help environment to read more on the subject.
In either case, the most sensible path forward is to run go install with the -x command-line option and see where the command tries to put the generated executable image, and why this fails (if at all).
You might study the output of go help install and go help build to read more on the subject.
You might also consider forcing usage of Go modules for your particular case:
running GO111MODULES=on go get github.com/linkedin/Burrow would work like five times faster for your use case.
Be sure to study the output of go help modules and go help mod-get first.
bin folder or src folders are not automatically created for you by the go get command. Here are the standard steps creating a new project in go assuming this the first time you are creating a project in go:
Under your workspace directory, create a project directory, say "project1" bin, src directories.
Set GOPATH, GOBIN:
export GOPATH=~/workspace/project1/
export GOBIN=~/workspace/project1/bin
Now if you need just the source code, do a go get github.com/linkedin/Burrow
or if you need a binary do a go install github.com/linkedin/Burrow
The binary will be stored under ~/workspace/project1/bin and source code under ~/workspace/project1/
Same steps would apply either if your creating your project through a make file or terminal

`go run hello.go` cannot find the "hello.go" file

I tried to run the program in command prompt #Go lang- But when i type run "go run hello.go" command i am gettin
CreateFile hello.go:The system cannot find the file specified
Please help to to compile and run the above marked program, Thanks in advance
As you can see from the output of running the dir command
earlier up in your shell session, there is indeed no file named "hello.go"
in the C:\GOCODE\testproject directory.
When you execute the
go run hello.go
command, the go tool tries to find the file named "hello.go" in the current
directory (because the name of that file is relative, so it's being
searched in current working directory). There's no such file,
and that's what go run tells you.
Unfortunately, from the outlook of your shell session, it appears there
are more problems with your setup.
And there are problems with your approach to Go.
First, while it looks like you're following
this guide (and this is the right thing
to do, actually), you misread it.
What it tried to tell you is that you should create the "src"
directory (and then the "hello" directory to contain your test project)
in the so-called workspace, and a list of workspaces known to Go
is stored in the GOPATH environment variable.
As you can see from the go env output, Go thinks you have a single
workspace located in C:\Users\Sitaram\Go.
Now it worth reiterating that—contrary to many (if not most) "mainstream"
languages,—Go is not "project-based"; instead, it requires all your code
to be organized in those workspaces, and it wants to know where these
workspaces are.
By default—if you did not explicitly set the GOPATH environment
variable,—it assumes your single workspace is located in the directory
named "go" placed in your "home folder".
And that's what you see in the go env output.
Now you have two options:
Set the GOPATH env. variable for your user to C:\GOCODE
then start another shell—so that it "sees" that variable and allows
the go tool to also see it and use).
Run go env to verify GOPATH contains C:\GOCODE.
Then follow the rest of the tutorial document:
Make sure there is the "src" folder directly under the C:\GOCODE.
Create your project folder directory under "src".
Let's say, it will be named "hello".
Under "hello", create that "hello.go" file.
Now cd C:\GOCODE\src\hello and then go build — you will have
the hello.exe created there.
Don't mess with GOPATH and just repeat the steps 2-4 from above
in the default workspace—C:\Users\Sitaram\go.
I'd go with the second variant because that inexplicable affection
of certain Windows users for polluting the C:\ with random personal
data is really an anti-pattern; have your personal belongings in your home
folder! Windows has gone a long way getting that right; and almost all
Windows software is finally there—understanding that paradigm. So why deviate?
Second, please unlearn go run.
I'm not sure the Go developers actually regret implementing it,
but people do really misinterpret what this tool is for.
It's for one-off throw-away "scripts".
Real development is done using go install and, sometimes, go build.
In most cases your normal development routine you use go install
exclusively — as it caches the results of compilation of all the packages
your project depends on. go build does not do this, and go run does
not even preserve the result of the compilation of your project itself.
Please read this quick reference card for more info.
After go get gpackage check if there is a yourproject.exe in your bin directory to compile your github package with your project.
If not, you have to do cd src/yourproject and type go install and hit enter.
Try execute the folowing command e check if corrected:
go env -w GOOS=windows

Consistent builds / remove personal information from binaries

I've now realized that Go saves absolute paths to source code in binaries for the purpose of printing stack-traces and the likes. I don't want to completely remove this information, however, this also means that every developer building the same program will produce an executable with a different checksum. Before I try to reimplement the build using chroot or something like that: isn't there any way to tell Go not to use absolute paths for this purpose?
I know it doesn't directly address what you asked, but #JimB's suggestion does indicate a class of solutions to the problem you seem to be having.
One of the easier ones (I think) would be to have your developers install Docker and create an alias so that the go command runs:
docker run --rm --tty --volume $GOPATH:/go golang:1.7.1(-$YOUR_PLATFORM) go
Then, every build (and test and run) thinks it's using a GOPATH of /go and your developers' checksums won't disagree based on that.
See here for more info.
isn't there any way to tell Go not to use absolute paths for this purpose?
Nowadays there is: -trimpath.
https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies explains:
-trimpath
remove all file system paths from the resulting executable.
Instead of absolute file system paths, the recorded file names
will begin either a module path#version (when using modules),
or a plain import path (when using the standard library, or GOPATH).

How to compile .go file to specific directory, or to gitignore the binaries?

Right now I'll just run go build __.go, but I'm wondering if it's possible to have that file built in a subdirectory (e.g. a /bin folder). It would just make gitignoring the binary files a lot cleaner, and right now I'm not really sure what else is a good approach as I'm also struggling to create a working gitignore exception rule that isn't just "Ignore all files, except .go files".
My current solution is naming the binary files every time I build them (e.g. go build -o hello.bin hello.go), but this seems laborious.
you can use the -o flag.
cd to the directory where you have the main.go file.
use this command - go build -o DirectoryPath
Where DirectoryPath is the location where you want to create the binary file to.
Instead of using go build *.go, you can do following:
Setup Go workspace, using this official go resource: How to write go code
Define GOBIN and GOPATH environment variable.GOBIN environment variable will point to the directory where you want to store your executables.GOPATH environment variable will point to the directory, where you've setup go workspace.
Now, instead of doing go build *.go, you can use go install {YourCodePath}, where {YourCodePath}, is relative path of your code in go workspace. And if the build is successful, you can find your executable in directory, pointed by GOBIN.

Can someone explain why GOPATH is convenient and how it should be used in general?

I am new to Go programming language and every tutorial starts off from setting GOPATH to current project folder.
Am I missing something? Is programmer really supposed to set GOPATH manually when he cd to his new Go project folder? I have read several FAQ entries about GOPATH but still couldn't wrap my head around it.
And why does GOROOT exist then? What's its purpose?
Are there any automatic tools which detects if current directory is root folder of Go project (for example by some hidden file) and changes GOPATH to this directory automatically?
Thank you, any advice really appriciated
ps. For example I develop completely disjoint Go projects A, B and C, should they live in single "workspace" environment? I guess not, but what I should do with GOPATH and GOROOT then?
The goal of the GOPATH is to centralize all packages into one common workspace. It is not really a new concept by itself (think of the Java Classpath for example), but Go's use is drastically simpler by not supporting packages versioning.
The Go programmer isn't supposed to set GOPATH manually when entering a new project folder. Each project folder is supposed to be a package by itself, and reside in the GOPATH along other packages, so GOPATH should be set only once. Tutorials begin by setting the GOPATH in order to isolate the tutorial workspace from anything else (or simply assuming that a user hasn't set the GOPATH, yet).
GOROOT is set to provide the standard packages to the Go programmer, you don't need to do anything with it. In short, there is a single rule for GOROOT: never, ever, touch it. Don't install anything in it, don't modify standard packages, etc.
I'm not aware of a tool to detect Go projects in the current directory, but it shouldn't be highly complex to create.
How you handle different projects is up to you. The Go way is to put every project as a package in the $GOPATH/src directory and do everything from there. As I don't really like it, I defined my GOPATH to be $HOME/.go. Then I put each project in a dedicated directory somewhere else (anywhere in my computer), and symlink the project directory into my $GOPATH/src dir. I can then use every Go toolchain command (e.g. go build myproject), use the project as package for another one, etc.
GOPATH allows you to collect dependency source code and the resulting compiled binaries in one place. This seems like a really attractive idea. However, I found myself working on several totally unrelated Go projects and an alternative approach suited me better.
This is a similar but different strategy to Elwinar's symlnks. I start a new project in an empty folder and create src. And I drop into the folder this shell script called env.sh:
if [ `type -p go` = "" ]; then
export PATH=$PATH:/usr/local/go/bin
fi
export GOPATH=$PWD
export PATH=$PATH:$PWD/bin
Each time I start work, I use
. env.sh
Note the dot and space - they matter.
Now, everything I do on this project is localised within this folder. It's possibly not the most widely-used strategy, but it works well for me.
And another thing: if your dependencies make use of environment variables for testing etc, you can put them in env.sh too. For example, Gorp has
export GORP_TEST_DSN=test/testuser/TestPasswd9
export GO_TEST_DSN=testuser:TestPasswd9#/test
Addendum
In the most recent Go versions, GOPATH is optional; if you don't set it, the default is $HOME/go. If you do set it and also want to use the new modules feature, set GO111MODULES=on also.
You don't need to set your GOPATH or GOROOT. GOPATH by default is under your user/home directory.
If no GOPATH is set, it is assumed to be $HOME/go on Unix systems and %USERPROFILE%\go on Windows. If you want to use a custom location as your workspace, you can set the GOPATH environment variable.
Go Modules
Now there's Go Modules support (since Go 1.11), so you don't have to use GOPATH anymore. For example, you can go to any directory on your system (outside of $GOPATH), and you can initialize a new Go module there, then you start working there. No GOPATH is needed.
You just need to do this once (while in a directory):
go mod init
$GOPATH: Go stores these files under it:
Source files ($GOPATH/src)
Compiled package files ($GOPATH/pkg)
Runnable files ($GOPATH/bin)
$GOROOT: Where the Go source code resides like Go Standard Library.
Also to run any go installed executable file from anywhere on your system, you might want to add $GOPATH/bin to your path environment variable like this:
export PATH=$PATH:$(go env GOPATH)/bin
More information check out this.

Resources