我们如何使go vet
,gofmt
和其他Go linter工具忽略vendor/
中的第三方文件,最好是具有准确的累积退出状态?
例如,find . -name vendor -prune -o -name '*.go' -exec gofmt -s -w {} \;
会提出有意义的退出状态吗?
答案 0 :(得分:5)
我经常做
go fmt $(go list ./... | grep -v /vendor/)
go test $(go list ./... | grep -v /vendor/)
但是自从我开始使用govendor
发现后,我可以使用govendor进行更少的输入
govendor fmt +l // +l is shorthand for local
答案 1 :(得分:3)
通常go list
比find
更有用:
$ go list ./...
arp242.net/trackwall
arp242.net/trackwall/cmdline
arp242.net/trackwall/vendor/arp242.net/sconfig
arp242.net/trackwall/vendor/bitbucket.org/pkg/inflect
[..trim..]
如您所见,这将列出当前目录中的所有包名称。要过滤vendor
目录,我们可以使用grep
:
$ go list ./... | grep -v /vendor/
arp242.net/trackwall
arp242.net/trackwall/cmdline
如果您想运行多个短节,报告所有错误,并且仅在成功时返回0
,您可以使用循环和状态变量:
#!/bin/sh
st=0
for pkg in $(go list ./... | grep -v /vendor/); do
echo "==> $pkg"
go vet "$pkg"
[ $? -ne 0 ] && st=1
golint "$pkg"
[ $? -ne 0 ] && st=1
# gofmt works on files, not packages
gofmt -d "${f#arp242.net/trackwall}"*.go
[ $? -ne 0 ] && st=1
done
exit $st
将输出如下内容:
==> arp242.net/trackwall
http.go:71: database/sql.NullString composite literal uses unkeyed fields
exit status 1
/home/martin/gocode/src/arp242.net/trackwall/http.go:70:2: don't use ALL_CAPS in Go names; use CamelCase
/home/martin/gocode/src/arp242.net/trackwall/http.go:75:9: if block ends with a return statement, so drop this else and outdent its block
==> arp242.net/trackwall/cmdline
Exit 1
当然,你不是第一个遇到这个问题的人,并且有一些工具基本上和上面一样,除了更好。 gometalinter可能是最知名的,我建议你使用它。它有用地包括一个--vendor
开关来忽略供应商目录:
$ go get -u github.com/alecthomas/gometalinter
$ gometalinter --vendor ./...
helpers.go:25:1:warning: realpath is unused (deadcode)
http.go:32:1:warning: _list is unused (deadcode)
[..trim..]
答案 2 :(得分:2)
感谢所有有用的建议!这适用于我的目的:
https://github.com/mcandre/go-ios7crypt/blob/ea8dd957e8f146ea20a57122870008a968875b53/Makefile
答案 3 :(得分:1)
您可以将所有源代码放入子目录(例如task CopyCommits() <<{
def grgit = org.ajoberstar.grgit.Grgit.open(dir: project.parent.projectDir)
grgit.checkout(branch: 'B')
'git cherry-pick 2133467'.execute().text.trim()
或internal
)。或者,您可以这样做:
lib
答案 4 :(得分:1)
使用Go 1.10(2018年第一季度),kind of tips的OP mcandre提及的answer将更加强大:
go list ./... | grep -v vendor | xargs go vet -v
如carpetsmoker的answer所示,依赖于(但未编译的)已销售软件包的软件包上的go vet
将失败:
==> arp242.net/trackwall
http.go:71: database/sql.NullString composite literal uses unkeyed fields
请注意,因为go issue 16086已解决!
请参阅this thread:
去兽医
“
go vet
”命令最适用于正在分析的包的完整类型信息。从历史上看,在各种情况下都存在问题:使用cgo
的软件包,使用vendoring的软件包以及没有安装最新依赖项的软件包都会导致vet
无法运行完整类型信息。不再。 “
go vet
”命令现在传递给vet
有关所有这些内容的完整信息,根据需要构建新的.a
文件(CL 74355和CL 74750)。<登记/> 现在,“go vet
”保证在分析包时具有最新的类型信息,这将提高其分析的准确性。
让build cache分摊构建这些.a
文件的成本是实现这一目标所需的最后一块。只有“
go vet
”才有此保证。不要使用“go tool vet
”,这对vet
工作的用户来说非常有用(就像您通常不会运行“go tool compile
”)。 以前您需要使用“go tool vet
”,如果您想要控制兽医标志,但“go vet
”现在接受“go tool vet
”所做的所有标志。 (参见“go help vet
”。)
答案 5 :(得分:0)
以跨平台的方式,我这样做philea -s "666 go vet %s" "666 go-fmt-fail %s"
产量,
$ ls -alh | grep ven
drwxr-xr-x 5 mh-cbon mh-cbon 4,0K 14 juin 20:43 vendor
$ philea -s "666 go vet %s" "666 go-fmt-fail %s"
go-fmt-fail ./local/local.go
✔ Success
go-fmt-fail ./dl/index.go
✔ Success
go vet ./local/local.go
✔ Success
go-fmt-fail ./gh/gh.go
✔ Success
go vet ./main.go
✔ Success
go vet ./gh/gh.go
✔ Success
go vet ./dl/index.go
✔ Success
go-fmt-fail ./main.go
✔ Success
答案 6 :(得分:0)
这是我使用的:
golint $(ls -d1 */ | sed s/\\//\\/.../g | grep -v -E "^vendor/" | tr "\n" " ")
答案 7 :(得分:0)
在 Go 1.9 中,为 ./...
引入了 change 以不再匹配 vendor
目录 (release notes) 中的包,这是一个流行的 {{3} }.
这意味着对于大多数目的,最简单的方法是现在
go test ./... # ignores vendor
go fmt ./... # ignores vendor
go list ./... # ignores vendor
# etc.
然而,特别是对于 gofmt
(如果 go fmt
没有我们需要的选项,我们可能想使用它),情况并不那么明确:
gofmt
将路径作为参数,而不是包gofmt .
应该工作 - 但这并不不忽略 vendor
所以要么我们必须回到
gofmt -l . | grep -v vendor
但是对于一个不是实际供应商目录的目录,这将匹配 vendor
,并且在丢弃它之前检查 vendor
中的所有内容感觉很浪费。 >
我们也不能用
gofmt -l $(go list -f '{{.Dir}}' ./...)
因为./...
与当前目录的包匹配,导致gofmt
下降到包括vendor
在内的所有地方。
使用模板直接迭代文件的更强大的解决方案
gofmt -l $(go list -f '{{range .GoFiles}} {{$.Dir}}/{{.}}{{end}}' ./...)
在具有长路径的大型目录树中可能会遇到命令行长度限制,因此这也不完美。我倾向于尽可能使用 go fmt ./...
。