I want to setup a CI system that it fails when code is not properly formatted according to goimports.
How I list my dirs:
go list -f {{.Dir}} ./...
/Users/felix/gocode/src/github.com/XXXX/YYY
/Users/felix/gocode/src/github.com/XXXX/YYY/cmd/foo
/Users/felix/gocode/src/github.com/XXXX/YYY/cmd/dev
/Users/felix/gocode/src/github.com/XXXX/YYY/pkg/monitoring/top
How I run goimports in the end:
goimports -l $(go list -f {{.Dir}} ./...)
/Users/felix/gocode/src/github.com/XXX/YYY/config.go
/Users/felix/gocode/src/github.com/XXX/YYY/raid_test.go
/Users/felix/gocode/src/github.com/XXX/YYY/vendor/github.com/shirou/gopsutil/disk/disk_freebsd.go
/Users/felix/gocode/src/github.com/XXX/YYY/vendor/github.com/shirou/gopsutil/disk/disk_linux.go
/Users/felix/gocode/src/github.com/XXX/YYY/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go
As you can see it also lists files within vendor. The execution also takes quite some time so I guess it's really checking all the files.
I really just care about the files outside vendor.
I think you use <1.9 Go version. Since 1.9 ./... shouldn't match vendor directory. See https://golang.org/doc/go1.9#vendor-dotdotdot.
Related
Is it possible to set the workdir to a different path?
For example, I want to run go build from the root path, but my source code is under a different directory, and I do not want to cd to it.
npm, for example, has the --prefix, which serves for this purpose.
Yes, its possible.
go build -o [output file path/name] [source code file path/name]
For example, if your source code file is located in projectdir/code/src/ and want to build and save output to projectdir/code/out, do following:
$ go build -o projectdir/code/out/main projectdir/code/src/main.go
As per go build documentation:
If the named output is an existing directory or ends with a slash or
backslash, then any resulting executables will be written to that
directory.
So our above build command can be rewritten like this:
go build -o projectdir/code/out/ projectdir/code/src/main.go
and it will generate executable named main in projectdir/code/out/ directory.
For more details, run go help build
No, this is not possible with 1.19. Just cd into it.
Go 1.20 (yet unreleased) brings the -C flag which might be what you want.
Is there an easy way to run go generate ./...
and in case that all the file in the pkg that call the generate didn't change- that go generate skip generating again this file?
(the reason is time consumption on generate)
For example:
-a (directory)
example1.go //contain //go:generate -output generated_example1.go
example2.go //contain //go:generate -output generated_example2.go
...
lets say i have 7 files to generate,
and I had changed only file 'example1.go'
so when i run go generate ./... I would like that it will not try to generate all the 7 files but only example1 because only this source has changed
(calling the go generate from inner directory will not solve the issue because there are couple of files to generate from same directory.)
This is not supported. The tool (command) you run with go generate may support this. See related: How to run go generate only for changed templates?
Some reasoning: go generate may be used to run arbitrary tool, not just source generation / manipulation tools, and running again may not have the same output / side effect. Also, running the tools may fail, and go generate does not keep a database of successful / failed runs, in which case it would not know which commands to run again even if source files didn't change.
All-in-all, your tool should check the existence of the desired output files (and their versions) to decide if (re-)generation is needed. This is easier than one might think though: since generation runs after the source file change, it's enough to compare the last modified timestamps. If the source (containing //go:generate) has a newer timestamp, generation should run. Otherwise it can be skipped. Note that go generate sets the $GOFILE env var to the base name of the file that triggered the command, so it's easy to check this.
I usually see ./... in golang
for example go test ./...or go fmt ./...
only know the meaning of one or two dots
It means perform the action on all packages under a directory. So for example go test ./... runs go test on the current dir + all subdirectories.
The Go tool documentation is here:
https://golang.org/doc/cmd
./... means a recursive action ( ... ) from your current directory ( ./ )
An import path beginning with ./ or ../ is called a relative path. The toolchain supports relative import paths as a shortcut in two ways.
First, a relative path can be used as a shorthand on the command line. If you are working in the directory containing the code imported as "unicode" and want to run the tests for "unicode/utf8", you can type "go test ./utf8" instead of needing to specify the full path. Similarly, in the reverse situation, "go test .." will test "unicode" from the "unicode/utf8" directory. Relative patterns are also allowed, like "go test ./..." to test all subdirectories. See 'go help packages' for details on the pattern syntax.
Second, if you are compiling a Go program not in a work space, you can use a relative path in an import statement in that program to refer to nearby code also not in a work space. This makes it easy to experiment with small multipackage programs outside of the usual work spaces, but such programs cannot be installed with "go install" (there is no work space in which to install them), so they are rebuilt from scratch each time they are built. To avoid ambiguity, Go programs cannot use relative import paths within a work space.
Run go help importpath or see the docs here https://pkg.go.dev/cmd/go#hdr-Relative_import_paths
This question already has answers here:
What do three dots "./..." mean in Go command line invocations?
(2 answers)
Closed 6 years ago.
I am having trouble understanding what the following command does.
go list ./...
When I look at the official documentation https://golang.org/cmd/go/#hdr-List_packages, it is not clear to me what the ./... argument is telling the command.
go list requires an import path for a package and can give you some listing info for the packages matched this way (you may be interested in its -f flag).
./... is a wildcard that matches the current folder and all of its subfolders (execute go help packages to read more about this somewhat hidden feature), and that can be used with all the built-in Go commands.
So go list ./... can list all the Go packages in the current folder and its sub-folders - you may want to call it from GOPATH for example.
go list ./...
Here ./ tells to start from the current folder, ... tells to go down recursively.
go list ...
In any folder lists all the packages, including packages of the standard library first followed by external libraries in your go workspace.
When you have multiple .go files in a main package, i need to list them all out when doing a go run.
So when i have main.go, a.go, b.go and they all belong to the main package, i need to type go run main.go a.go b.go in order to use functions and structs inside the other 2 go files. The go build command however, is smart enough to link all files together automatically.
Have i misunderstood something about Go, or is this normal (listing out all the files in the main package when doing a go run)?
The short answer is: you need to list them all out. You can do this with shell tricks, if you're desperate. I usually just write a shell script to go build and then run the resulting executable, after it gets too annoying.
# this works unless you have _test.go files
go run *.go
# if you really want to... enable extended glob
shopt -s extglob
# so you can do something like this (matches all .go except *_test.go files)
go run !(*_test).go
Check out this thread: https://groups.google.com/forum/#!topic/golang-nuts/EOi0VAQNA4c
If your source is in $GOPATH/src
as in
$GOPATH/src/somedir/main.go
$GOPATH/src/somedir/a.go
$GOPATH/src/somedir/b.go
doing "go install somedir" will compile and install the somedir binary in to $GOPATH/bin
no need to list out the files individually
"go install" finds all the files on it's own.
My common work cycle with go is (from my bash prompt):
$ clear; go install myproj && $GOPATH/bin/myproj
which, clears the screen, builds and installs "myproj" and then runs it
so, after I change code, I just hit Ctrl-C, Up arrow, and enter.
Entire cycle time is ~1 second (for small to start stuff)