Go doesn't find /usr/share/zoneinfo in docker container - go

In a Go program I call time.LoadLocation("Europe/Berlin") and it returns an error saying open /usr/local/go/lib/time/zoneinfo.zip: no such file or directory, even though in the container (running alpine:3.9 with tzdata installed) /usr/share/zoneinfo/Europe/Berlin exists and, according to the docs, should take precedence over the zip file. The same program finds the file on my machine (Arch Linux). The executable got statically linked on my machine and then copied into the container. I tried Go 1.11.5 and 1.10.3.
I built the executable with:
CGO_ENABLED=0 go build -a -ldflags "-s" -o gocake_static
I'm looking for any ideas that help me identify the problem.

if you use only one static zoneinfo. maybe FixedZone can solve your problem.
It does not require timezone.zip, thus no need to download zoneinfo.zip and set env ZONEINFO in Dockerfile.
for example
loc := time.FixedZone("Europe/Berlin", 1*60*60)
fmt.Println(time.Now().In(loc).Format("2006-01-02 15:04:05"))

Related

go install c shared output path

i'm trying to install a library inside a package. However I don't understand where it compiles to.
Structure is like so:
package/cmd/library
I can install other executable targets fine with go install. My paths are set correctly. However now I want to build my shared library target and deploy it somewhere (this deployment step can be done manually). I'm running into two different issues.
Issue one, I can't seem to install it at all:
go install -buildmode=c-shared bpackage/cmd/library#latest
Returns with:
go install: no install location for directory /home/tpm/go/pkg/mod/package/cmd/library outside GOPATH
For more details see: 'go help gopath'
which tells me that it installs somewhere other than in my gopath, I'm just not sure where that might be.
Issue 2, using the -o flag doesn't work with go install, so I can't seem to alter the output location to place it inside the GOPATH (i did try setting the GOBIN to within my gopath, but since other commands work fine I don't think this should be causing any issue)
Quoting Ian from https://github.com/golang/go/issues/24253
Note that it doesn't make a great deal of sense to use go install -buildmode=c-shared. The expectation is that people will use go build -buildmode=c-shared -o foo.so. The only point of using -buildmode=c-shared is to use the shared library somewhere, and using go install without -o will put the shared library in a relatively unpredictable place.

How to `go install` to bin inside module dir?

For example, when I run this
GOOS="windows" GOARCH="386" go install ./something
The executable would be created at
$GOROOT/bin/$GOOS_$GOARCH/something.exe
I want the executable to be created at
path/to/my/module/bin/$GOOS_$GOARCH/something.exe
EDIT
To clarify, I ask the question in the context of cross compiled builds inside a module.
I get the desired result using this command inside my module. I'd like to avoid specifying the path.
GOOS="windows" GOARCH="386" go build -o ./bin/$GOOS_$GOARCH/something.exe ./something
So, is it possible to get the same with go install?
Setting GOBIN results in an error
GOBIN=$(pwd)/bin GOOS="windows" GOARCH="386" go install ./something
# go install: cannot install cross-compiled binaries when GOBIN is set
Don't use go install for cross compiling. Use go build with -o flag.
Here is some history regarding GOBIN, robpike posted an issue stating "I have $GOBIN set but the go tool is ignoring it when installing..."
This article mentions
"When cross compiling, you should use go build, not go install. This is the one of the few cases where go build is preferable to go install...
The reason for this is go install always caches compiled packages, .a files, into the pkg/ directory that matches the root of the source code...
This logic also holds true for the standard library, which lives in /usr/local/go/src, so will be compiled to /usr/local/go/pkg/$GOOS_$GOARCH. This is a problem, because when cross compiling the go tool needs to rebuild the standard library for your target, but the binary distribution expects that /usr/local/go is not writeable.
Using go build rather that go install is the solution here, because go build builds, then throws away most of the result (rather than caching it for later), leaving you with the final binary in the current directory, which is most likely writeable by you"

Where does go get install packages?

I've been given instructions to run go get <some-remote-git-repo> which seems to succeed, but it's not clear to me where the package was installed to so I can run an executable from it.
Per https://golang.org/doc/code.html#remote it seems it will be installed in $GOPATH/bin but $GOPATH isn't defined in my shell (though the go get command seems to work fine). Go is installed via Homebrew.
I found the missing clue by running brew info go, which says:
==> Caveats
A valid GOPATH is required to use the `go get` command.
If $GOPATH is not specified, $HOME/go will be used by default:
https://golang.org/doc/code.html#GOPATH
From that I found the executable in question at $HOME/go/bin.
go env
you can get the path from GOMODCACHE
I had a similar problem which is why I found your question. However, in my case I did not have an empty GOPATH but one with multiple directories. I worked out the issue and describe it here...
If you run go get and you already have the package it says nothing (even with the -v option). This is confusing if it's not in the first directory of your GOPATH. Ie you run go get , there is no error or any message but when you check the first directory of the GOPATH (which is where the doc says it should be) you can't find it.
I eventually found it, but since I have a large GOPATH this was rather tedious.
Even if you don't have a $GOPATH variable you can see what it uses by doing go env GOPATH.
Try this to see what your path is:
echo `go env GOPATH`/bin
Using go build
Try this with main.go. In your greeter directory, run the following command:
go build
In this case, you built your greeter application into an executable file that was added to your current directory. Check this by running the ls command:
ls
./greeter

go tool: no such tool "tour"

I'm trying out Go for the first time. I was following these docs and wanted to run the go tour locally, but I haven't figured out how to get it to work.
Where is the tool "tour" supposed to be found?
I'm on OSX 10.11.3, and I installed Go via Homebrew
my Go entries in .zshrc
export GOPATH=$HOME/code/Go
export GOROOT=/usr/local/opt/go/libexec
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
tour is not installed by default with an installation of go. You need to go get it:
go get golang.org/x/tour/gotour
Docs: https://github.com/golang/tour/
I had a problem too. This's my solution, on OSX let try
gotour
With version go1.8.1 darwin/amd64
It works for me using go1.4, but not with go1.7. If you just run go tool, it gives you a list of known tools. They seem to have removed it from tools.
$ gvm use go1.7
$ go tool
addr2line
api
asm
cgo
compile
cover
dist
doc
fix
link
nm
objdump
pack
pprof
trace
vet
yacc
$ gym use go1.4
$ go tool
6a
6c
6g
6l
addr2line
cgo
cover
dist
fix
nm
objdump
pack
pprof
tour # <--- here
vet
yacc
Firstly, it is no longer gotour. And secondly, for the time being, the tour package is located at: golang.org/x/website/tour as opposed to what A Tour of Go Welcome Page says.
So, at least for now:
The correct way to get tour is:
go get golang.org/x/website/tour
Or,
go install golang.org/x/website/tour#latest
After which you can run the command in the terminal:
$ tour
2021/06/22 17:46:48 Serving content from /home/user/go/pkg/mod/golang.org/x/website/tour#v0.0.0-20210616181959-e0d934b43647
2021/06/22 17:46:48 A browser window should open. If not, please visit http://127.0.0.1:3999
2021/06/22 17:46:52 accepting connection from: 127.0.0.1:33192
To find out where it has been installed, you can do which tour:
$ which tour
/home/user/go/bin//tour
reference
Because of changes in Go package management and introduction of modules, this has changed since the original question. Thus, for future reference (as this is the first Google result), if you have not configured GOPATH environment variable
go get golang.org/x/tour
$HOME/go/bin/tour
Note that the executable is called "tour" instead of "gotour".
Source (with full explanation of why and details): https://stephencharlesweiss.com/getting-going-with-golang/
I've got:
golang.org/x/tour/gotour has moved to golang.org/x/tour
So, this works for me:
go get golang.org/x/tour
then:
tour
When you install go, tour is not installed by default. You need to do a go get golang.org/x/tour/gotour. This downloads gotour in your workspace.
If you configured your PATH properly, gotour command from anywhere in the terminal will open up your browser, but if PATH is not configured properly, do a
$GOPATH/bin/gotour
This command can be used from anywhere in your command line and it opens tour in your default browser
http://whipperstacker.com/2015/09/27/how-to-run-the-go-tour-locally/
https://github.com/golang/tour/blob/master/README.md
Once gotour is installed, it’s executable like other executables are typically stored in the bin directory of your workspace. Inside the bin directory ./gotour will invoke or start gotour, elsewhere the gotour will need to be preceded by a path to where the executable is located. In other words $GOPATH/bin/gotour will invoke or start gotour when you are not inside the bin directory.

Building small container for running compiled go code

From
https://docs.docker.com/articles/baseimages/
I am trying to build a base image to run compiled go code, from:
https://github.com/tianon/dockerfiles/tree/master/true
I have tried to copy into docker the true.goThen: exec: "/true": permission denied
Also tried to bash into it, then: "bash"Then: executable file not found in $PATH
Also tried to use the debootstrap raring raring > /dev/null Then: "bash": executable file not found in $PATH
How do you do this?
Thanks
I'm not sure I entirely follow.
The Dockerfile from the linked project builds an image with nothing in it except an executable - there will be no shell or compiler, so running bash will be impossible. It does this by using the special scratch base image, which is simply a completely empty filesystem.
If you clone the repository and build the image using the Dockerfile (docker build -t go-image .), it will simply copy the executable directly into the image (note the Dockerfile copies the executable true-asm, not the source code true.go). If you then use docker run to start the image, it will run it (docker run go-image).
Does that make sense? The code is compiled locally (or by another container) and the compiled, stand-alone executable is placed by itself into the image.
Generally, you don't want to do this and definitely not when you're beginning - it will be easier for you to use a golang or debian image which will include basic tools such as a shell.

Resources