Golang profiler cannot find source code - go

I've included the net/http/pprof package in my code. I can then comfortably run the pprof profiler (on Debian):
go tool pprof http://localhost:9000/debug/pprof/profile
Commands such as top10 or even generating call graphs work as expected. However, as soon as I try to go into a function, it fails:
(pprof) list MyFunc
No source information for mypkg.MyFunc
My GOPATH is set to my project's directory. Do I need any special flags or environment variables while building my source code or while running pprof?

Found the answer with the help of the golang-nuts people. I needed to specify the binary:
go tool pprof mybinary http://localhost:9000/debug/pprof/profile
This way the source code is found and can be listed with the "list" command.

I had the same problem with "net/http/pprof", albeit on windows.
Using "runtime/pprof" instead, with pprof.StartCPUProfile / StopCPUProfile solved it.

Related

In vscode-go, is there a way to run the local version of a tool for go:generate statements?

In many projects, I have a tools/tools.go file that allows me to have local versions of the tools I use (reference).
I also have go:generate statements in my code to automate the generation of mock files using https://github.com/golang/mock/mockgen. I have a local version of mockgen under a bin folder of my project and I can generate all the mocks of my project by running something like PATH=./bin:${PATH} go generate ./....
Vscode-go recognizes the go:generate statements in the code and can generate code for us.
I would like to know if there is a way to get vscode-go to run mockgen (through gopls.generate) using the local version I have under the bin directory.
With the setting go.alternateTools, vscode-go lets us specify an alternate path for the tools used by the extension (i.e. dlv). I tried to configure that option for mockgen but it didn't change anything. My guess is that it does not work because vscode-go runs mockgen through gopls.generate; it does not run mockgen directly. But this is just a guess.
Below is the error I get if I don't have a mockgen binary in my $PATH:
[Info - 5:44:18 PM] 2021/08/08 17:44:18 xxxxxxx.go:19: running "mockgen": exec: "mockgen": executable file not found in $PATH
operation="generate"
Does anyone have any idea? ๐Ÿ˜…
Edit: see #Zyl's comment there for a very good alternative.
I've run into the same problem today. Found this solution, which worked for me if someone needs this in future:
export GOPATH="$HOME/go"
export PATH="$GOPATH/bin:$PATH"
And then run (in the directory where file with the "go:generate" comment is located)
go generate

Cross compile from Windows to Linux using os/exec Command

The title mostly says it. I know that I can do
set GOOS=linux
set GOARCH=amd64
in cmd before I go build, but I'm trying to write a build script and do it all with exec.Command.
My go build -o etc works with exec.Command (it builds), but when printing out GOOS in a test script after either of this commands:
cmd := exec.Command("set", "GOOS=linux")
// OR
cmd := exec.Command("set GOOS=linux")
I get windows.
Any ideas? Thanks!
I strongly suggest you just use a tool like Gox instead. It cross-compiles into every supported build target by just executing gox. It also has options if you only want to build for certain targets.
As for the code you're asking about, exec.Command doesn't create a new process, or really do anything other than create a Cmd struct. The os/exec documentation (specifically the docs for the Command function) has an example of what you seem to be trying to do- execute another program with custom environment variable assignments... see the Example (Environment) section of the linked documentation and try to follow that structure if you still want to cross-compile your way.

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).

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.

`go build` rebuilds unnecessarily

go build and go run are very slow on a tiny program I have (cgo invocations in particular). I'd like go to cache the binary so that it only rebuilds when the source is newer. I would use a simple Makefile with a % rule, but the language designers claim that go's build support doesn't need Makefiles.
Is there another alternative I've overlooked? Does the go community prefer another build system, maybe hash-based instead, for caching and reusing build products?
go build and go install will soon (Go 1.10, Q1 2018) be much faster: see this thread and this draft document.
The go command now maintains a cache of built packages and other small metadata (CL 68116 and CL 75473). The cache defaults to the operating system-defined user cache directory but can be moved by setting $GOCACHE.
Run "go env GOCACHE" to see the current effective setting. Right now the go command never deletes anything from the cache. If the cache gets too big, run "go clean -cache" instead of deleting the directory. That command will preserve the cache's log.txt file. In a few weeks I'll ask people to post their log.txt files to a Github issue so that we can evaluate cache size management approaches.
The main effect of the build cache is that commands like "go test" and "go build" run fast and do incremental builds always, reusing past build steps as aggressively as possible.
You do not have to use "go test -i" or "go build -i" or "go install" just to get fast incremental builds. We will not have to teach new users those workarounds anymore. Everything will just be fast.
Note that go install won't installs dependencies of the named packages: see "What does go build build?".
I wrote a tool that happens to solve this as a side effect. go build alone will not check if the executable it's producing is already up to date. go install does, and if you tweak it to install to a location of your choice, then you'll get the desired result, similar to go build.
You can see the behaviour you describe by doing something like this:
$ go get -d github.com/anacrolix/missinggo/cmd/nop
$ time go run "$GOPATH"/src/github.com/anacrolix/missinggo/cmd/nop/*.go
real 0m0.176s
user 0m0.142s
sys 0m0.048s
That's on a warm run. go run will link on every invocation, just as go build would. Note that github.com/anacrolix/missinggo/cmd/nop is an program that does absolutely nothing.
Here's invoking the same package, using my tool, godo:
$ time godo github.com/anacrolix/missinggo/cmd/nop
real 0m0.073s
user 0m0.029s
sys 0m0.033s
For larger programs, the difference should be more pronounced.
So in summary, your standard tooling option is to use go install, or an alternative like godo.

Resources