Open kvii opened 4 months ago
经过查询,发现 wire 那边更新了版本。新版本的 wire_gen.go 和当前的不太一样(相关 issue)。 解决的方式也很简单,直接 cd cmd/server 然后重新执行下 wire 就行了。 但引出了个新问题,go 1.22 执行 go generate ./... 会报错(wire issue)。需要将 wire 升级到 v0.6.0 解决这个问题。
To address the issue with go generate ./...
failing after creating a project with kratos new
, especially due to missing go.sum
entries for modules required by the wire
tool, follow these steps:
Update Your go.mod
File: Ensure it reflects the latest versions of dependencies, particularly the wire
tool. Run go mod tidy
to clean up and update go.mod
and go.sum
files, adding any missing module requirements and removing unnecessary ones.
Check Wire Tool Invocation: With the wire
version update, verify if the invocation method in wire_gen.go
is still valid. Adjust according to any new guidelines provided by the wire
tool's documentation.
Manually Run Wire: Execute go run github.com/google/wire/cmd/wire
in the directory with your wire.go
file for more detailed error messages, which can help identify configuration issues or missing dependencies.
Review Wire's Release Notes: Look for any breaking changes or new requirements in the latest wire
version that might affect your project. Update your code and dependencies as needed.
Ensure Correct Package Imports: Make sure all imported packages in your wire_gen.go
file and project are correct and accessible, updating import statements if necessary due to the wire
update.
By following these steps, you should be able to resolve the errors related to missing go.sum
entries and successfully run go generate ./...
in your Kratos project.
To continue the conversation, mention @dosu.
然后在升级完之后,运行 go generate ./... 后会在 go.sum 文件中掺杂一些未依赖的项目,需要执行一下 go mod tidy。 我认为 make generate 下面的内容也需要更新一下。
我看了一下Issue和对应的PR,我感觉改的有点Breaking change了,不太能持续发展。
我通过复现了几种情况,认为删除 go get github.com/google/wire/cmd/wire@latest
和 go mod tidy
是不可取的,因为当后续版本迭代,这无法预计后续内容。
在末尾添加go mod tidy
我是认同的,不然无法执行后续的 go build
和 kratos run
我的建议是 这个PR进行常规的 go get
更新各个依赖的版本,然后在 makefile
里面的generate 末尾只添加go mod tidy
同时我也提了一个PR,将 project crate successed 的Prompt 改成了 make generate
@mo3et Makefile 里的那句 go get github.com/google/wire/cmd/wire@latest
是 go get 而非 go install。它不是要去下载 wire,而是在 go generate 运行到 wire_gen.go 前先临时在工程里下载一些依赖。当前版本如果不这样做的话 go generate 就会报上面的错误。
另外 wire_gen.go 里用的不是 $PATH 里的那个 wire,而是使用 go run 直接执行的。代码在这里:
其中,go run
可以跳过 install,直接执行远程的 go 库程序(貌似是 1.20 左右的新特性)。比如下面的命令可以直接打印 kratos 的版本。这样就不需要先执行 go install .../kratos/v2@latest
然后再执行 kratos --version
了。
$ go run github.com/go-kratos/kratos/cmd/kratos/v2@latest --version
kratos version v2.7.3
如果 Makefile generate 里的那句 go get github.com/google/wire/cmd/wire@latest
使用来在执行 go generate ./...
前下载最新的 wire.exe 的话。那现在 wire_gen.go 里用又的不是 $PATH 里的那个 wire.exe。所以这句代码就没有执行的必要了。如果这 get 和 tidy 这两句是用来更新依赖的话,那就更应该被删除了不是吗?
其实你说的基本都是对的,昨晚和朋友@alilestera花了些时间把这些情况都复现了一下,要是有问题也请轻喷。
首先先从issue的问题开始,为什么会出现这个问题呢,其实和wire的版本关系不大,或者说不是重点。因为主要的问题是在执行wire的cmd,在项目中并没有被导入,所以导致了go mod tidy
,他就会被干掉。所以在go generate
,或者说 go run
的时候会缺少依赖包。wire真正的问题是在于 使用go 1.22.2时,wire v0.5.0 会发生panic。
wire 解决了上面问题是在 go run
中添加了mod 的flag,会自动更新go mod. Ref
所以上述部分没有问题
下面的go get是为了下载依赖没有任何问题,不然会和刚刚一样,如果执行了tidy,会认为cmd/wire
是没有导入,不需要的包,会被剔除go.sum
wire_gen.go
在 generate 命令中也是使用的 go run 来生成的,而不是binary。
不过关于go run
的直接执行远程的go库程序,这个描述我有点不太理解。我找了个初始化的环境执行,还是会下载到本地编译执行的。这不是拉取然后在对应路径执行 main.go
么?install是直接下载已经编译完成的binary来执行,go run 是编译并执行,确实不是一个路径。
最后回到我认为最关键的争议点上,就是说用的不是bin的 wire,所以没有更新的必要。
这个并不是不需要更新,而是在新的go generate里面,-mod=mod
这个flag 执行了自动更新 go.mod 的操作,来获取所需的内容。
tidy 和 get wire就是为了可以使这个go run 可以顺利生成,也能说是折中的方法。这就是为什么老版本的wire文件 make generate可以,但是在特定条件的go generate不行。
你的方法和改动我是认同的,但是我觉得这个删除内容还是太激进了,不能模拟足够多的test。
举个例子 假设说 clone了这个layout,然后有人用wire v0.5 的binary进行生成, generate的内容被改动。然后有协作者拉取了这个repo,但是并没有这些依赖,还是会出现相应的问题。 在我看来 Makefile
不单单只是个 Execute,也是个 Reference,所以为了兼容各种无法预料的情况,还是按一个最标准化的流程来是最为稳妥。毕竟用Kratos 投入生产的公司不在少数。我的想法还是遵循着增加而不是删除,或者说没有致命错误的内容,可以正常执行的情况下不进行变动。
这个issue说白了还是 layout 更新的版本不及时,这个PR应该是一个常规的dump 各个依赖的版本,也就能解决问题了。毕竟在推荐和常用的应该还是 go install的 wire binary.
在最后的go mod tidy
可加可不加,加了保证项目整洁性,不加就多了个subcommand
包,这个冗余为了后面的wire不用频繁获取,也是可以接受的。
实在不行的话,咱们就召唤maintainer,看看他是怎么理解的。😁
通过复现步骤,我遇到与 @kvii 一样的错误。但经过摸索,我得到的原因有些不同。
go generate ./...
时,会执行 wire_gen.go 里的go run github.com/google/wire/cmd/wire
,而当前 kratos-layout 的 go.mod / go.sum 缺少其所需依赖,所以会提示错误missing go.sum entry for module ...
。go run -mod=mod github.com/google/wire/cmd/wire
,前后唯一差异就是-mod=mod
,添加这个 flag 会自动更新 go.mod,因此执行命令go generate ./...
不再会出现问题。解决的方式也很简单,直接 cd cmd/server 然后重新执行下 wire 就行了。
我猜测是自己有 wire 的可执行文件,并且版本是 0.6.0 的。
@alilestera
我猜测是自己有 wire 的可执行文件,并且版本是 0.6.0 的。
是的,我这句话的意思就是“用新版本的 wire 重新去 cmd/xxx 重新生成一遍 wire_gen.go”。PR 里那个 "-mod=mod" 不是我手写的,而是我使用新版 wire 生成的。这就好比 protobuf 升级后我重新执行 make api
重新生成 pb.go 一样。
总结一下,大体逻辑是这样的:
本来 v0.5.0 到 v0.6.0 除了这个 "-mod=mod" 以外没有其他逻辑上的变动,生成完 wire_gen.go 之后不改 go.mod 里的版本也完全 OK。但是 wire v0.5.0 底层依赖的 golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b 在开发环境是 go 1.22 的时候会 panic(相关 issue) 。所以在 v0.6.0 时升级了这个依赖。
现在回到 layout 这边,因为 Makefile 里的 generate 里有一句 go get github.com/google/wire/cmd/wire@latest
,所以 make generate
在执行到 go generate ./...
前就把工程里的 wire 版本升到了 v0.6.0,所以才不会出问题。
贴一个 go 1.22 panic 的最小复现:
# 本地要安装 go 1.22
# 创建一个新工程
$ kratos new playground
$ cd playground
# 若要查看之后的命令对工程的更改,可以加一句:
# git init && git add -A
# 重新生成 wire_gen.go,解决缺依赖的问题。
$ cd cmd/playground
$ wire
# 输出
# wire: playground/cmd/playground: wrote /Users/kvii/workspace/qs/go/kratos/playground/cmd/playground/wire_gen.go
# 回到根目录执行 go generate
$ cd ../../
$ go generate ./...
# panic: runtime error: invalid memory address or nil pointer dereference [recovered]
# panic: runtime error: invalid memory address or nil pointer dereference
# [signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x104ef0c84]
# goroutine 359 [running]:
# go/types.(*Checker).handleBailout(0x14000168400, 0x1400098fb98)
# /usr/local/go/src/go/types/check.go:367 +0x9c
# panic({0x105050180?, 0x1051fe880?})
# /usr/local/go/src/runtime/panic.go:770 +0x124
# go/types.(*StdSizes).Sizeof(0x0, {0x105093ac8, 0x105202d00})
# /usr/local/go/src/go/types/sizes.go:228 +0x314
# go/types.(*Config).sizeof(...)
# /usr/local/go/src/go/types/sizes.go:333
# go/types.representableConst.func1({0x105093ac8?, 0x105202d00?})
# /usr/local/go/src/go/types/const.go:76 +0x9c
# go/types.representableConst({0x1050956d0, 0x1051f7230}, 0x14000168400, 0x105202d00, 0x1400098dd28)
# /usr/local/go/src/go/types/const.go:92 +0x138
# go/types.(*Checker).representation(0x14000168400, 0x140009aa180, 0x105202d00)
# /usr/local/go/src/go/types/const.go:256 +0x68
# go/types.(*Checker).implicitTypeAndValue(0x14000168400, 0x140009aa180, {0x105093ac8, 0x105202d00})
# /usr/local/go/src/go/types/expr.go:375 +0x304
# go/types.(*Checker).assignment(0x14000168400, 0x140009aa180, {0x105093ac8, 0x105202d00}, {0x104fbf5d7, 0xe})
# /usr/local/go/src/go/types/assignments.go:52 +0x23c
# go/types.(*Checker).exprInternal(0x14000168400, 0x0, 0x140009aa180, {0x105094de8, 0x1400051e8c0}, {0x105093b18, 0x1400099c000})
# /usr/local/go/src/go/types/expr.go:1175 +0x1dc8
# go/types.(*Checker).rawExpr(0x14000168400, 0x0, 0x140009aa180, {0x105094de8?, 0x1400051e8c0?}, {0x105093b18?, 0x1400099c000?}, 0x0)
# /usr/local/go/src/go/types/expr.go:979 +0x12c
# go/types.(*Checker).exprWithHint(0x14000168400, 0x140009aa180, {0x105094de8, 0x1400051e8c0}, {0x105093b18, 0x1400099c000})
# /usr/local/go/src/go/types/expr.go:1563 +0x64
# go/types.(*Checker).indexedElts(0x14000168400, {0x14000168200, 0x1b, 0x400000?}, {0x105093b18, 0x1400099c000}, 0xffffffffffffffff)
# /usr/local/go/src/go/types/index.go:453 +0xd4
# go/types.(*Checker).exprInternal(0x14000168400, 0x0, 0x1400051f980, {0x105094de8, 0x1400051f140}, {0x0, 0x0})
# /usr/local/go/src/go/types/expr.go:1247 +0xd58
# go/types.(*Checker).rawExpr(0x14000168400, 0x0, 0x1400051f980, {0x105094de8?, 0x1400051f140?}, {0x0?, 0x0?}, 0x0)
# /usr/local/go/src/go/types/expr.go:979 +0x12c
# go/types.(*Checker).expr(0x14000168400, 0x0?, 0x1400051f980, {0x105094de8?, 0x1400051f140?})
# /usr/local/go/src/go/types/expr.go:1513 +0x38
# go/types.(*Checker).varDecl(0x14000168400, 0x1400017ecc0, {0x140003441a0, 0x1, 0x1}, {0x0, 0x0}, {0x105094de8, 0x1400051f140})
# /usr/local/go/src/go/types/decl.go:521 +0x140
# go/types.(*Checker).objDecl(0x14000168400, {0x105097d78, 0x1400017ecc0}, 0x0)
# /usr/local/go/src/go/types/decl.go:194 +0x7ec
# go/types.(*Checker).packageObjects(0x14000168400)
# /usr/local/go/src/go/types/resolver.go:693 +0x468
# go/types.(*Checker).checkFiles(0x14000168400, {0x140003440b8, 0x1, 0x1})
# /usr/local/go/src/go/types/check.go:408 +0x164
# go/types.(*Checker).Files(...)
# /usr/local/go/src/go/types/check.go:372
# golang.org/x/tools/go/packages.(*loader).loadPackage(0x1400016c000, 0x14000098750)
# /Users/kvii/go/pkg/mod/golang.org/x/tools@v0.6.0/go/packages/packages.go:1052 +0x870
# golang.org/x/tools/go/packages.(*loader).loadRecursive.func1()
# /Users/kvii/go/pkg/mod/golang.org/x/tools@v0.6.0/go/packages/packages.go:851 +0x178
# sync.(*Once).doSlow(0x0?, 0x0?)
# /usr/local/go/src/sync/once.go:74 +0x100
# sync.(*Once).Do(...)
# /usr/local/go/src/sync/once.go:65
# golang.org/x/tools/go/packages.(*loader).loadRecursive(0x0?, 0x0?)
# /Users/kvii/go/pkg/mod/golang.org/x/tools@v0.6.0/go/packages/packages.go:839 +0x50
# golang.org/x/tools/go/packages.(*loader).loadRecursive.func1.1(0x0?)
# /Users/kvii/go/pkg/mod/golang.org/x/tools@v0.6.0/go/packages/packages.go:846 +0x30
# created by golang.org/x/tools/go/packages.(*loader).loadRecursive.func1 in goroutine 209
# /Users/kvii/go/pkg/mod/golang.org/x/tools@v0.6.0/go/packages/packages.go:845 +0x84
# exit status 2
# cmd/playground/wire_gen.go:3: running "go": exit status 1
再贴一个用了 make generate
之后,go generate ./...
就不会出问题的复现:
# 同上面复现的基础步骤
$ kratos new playground
$ cd playground
# git init && git add -A
$ cd cmd/playground
$ wire
# 回到根目录
$ cd ../../
# 检查下 go.mod 里的 wire 版本,是不是没有被更改?
cat go.mod | grep wire
# github.com/google/wire v0.5.0
# 先执行 make generate,再执行 go generate ./...
# 看看后一句还会不会 panic。
$ make generate
# 把更新都暂存,证明是 make generate 修改了 go.mod 里 wire 的版本。
# git add -A
$ go generate ./...
# 看看这次运行 go generate ./.. 有没有 panic?
# git status 看看 go.mod 文件有没有被修改?
# 现在再看看 go.mod 里 wire 的版本
cat go.mod | grep wire
# github.com/google/wire v0.6.0
直接更新最后的提示可以吗?
例如这一段:
🍺 Project creation succeeded greet
💻 Use the following command to start the project 👇:
$ cd greet
$ go generate ./...
$ go build -o ./bin/ ./...
$ ./bin/greet -conf ./configs
更新为(注意generate和build):
🍺 Project creation succeeded greet
💻 Use the following command to start the project 👇:
$ cd greet
$ make generate
$ make build
$ ./bin/greet -conf ./configs
更新提示之后,用户就会按照提示的执行命令(比如我),这样就不会出现go generate ./...
的问题了。
@zzhaolei 有到是有这么个 pr,就是上面的 contributor 提交的 https://github.com/go-kratos/kratos/pull/3313 但不知道为啥给关了。
我本人还是希望能通过升级 wire 版本来解决问题。毕竟这个坎总是要跨过去的
复现步骤:
kratos new playground
创建一个工程。cd playground
进入工程。go generate ./...
(而非 make generate)。然后就会遇到这个错误: