我很难过这个.在我正在进行的项目中,我们从Thrift生成go代码.代码在包A/B/thriftapi中创建(以前是A/B/thrift导致问题,因为所有生成的代码都是导入git.apache.org/thrift.git/lib/go/thrift并导致名称冲突).
我生成代码并将代码移动到$GOPATH/src/A/B/D 我然后尝试构建我的项目并且收到了大量的表单错误:
p.X.Read undefined (type Foo has no field or method Read)
Run Code Online (Sandbox Code Playgroud)
我看了一条令人讨厌的台词:
import (
"A/B/D"
"git.apache.org/thrift.git/lib/go/thrift"
)
func(p *Bar) readField1(iprot thrift.TProtocol) error {
p.X = D.NewFoo()
if err := p.X.Read(iprot); err != nil {
...
}
Run Code Online (Sandbox Code Playgroud)
由于我使用的是IntelliJ,因此我按CTRL +点击该Read()方法,确定它会跳转$GOPATH/A/B/D/ttypes.go到该方法
func (p *Foo) Read(iprot thrift.TProtocol) error {
...
}
Run Code Online (Sandbox Code Playgroud)
这正是我期望该方法所在的文件,它是一个指针上的方法,Foo所以没有问题.一切似乎都应该是正确的,但是在IntelliJ和命令行中我都遇到了这些问题.
什么想法可能会出错?当它告诉我方法不存在时会令人沮丧,但如果我点击它(并且还会在智能感知中弹出),它会让我正确
编辑 - 每条评论
type Bar struct {
X Foo `thrift:"x,1,required"`
}
Run Code Online (Sandbox Code Playgroud)
这是您所看到内容的最小复制。
package main
type A struct{}
type B *A
func (a *A) Read() {}
func main() {
var b B
b.Read()
}
Run Code Online (Sandbox Code Playgroud)
编译产生此错误信息:
prog.go:11: b.Read undefined (type B has no field or method Read)
Run Code Online (Sandbox Code Playgroud)
问题在于,节俭正在定义它的本身Foo,这就是*D.Foo的类型b.X。的D.Foo类型被表示为A在我的代码,和Foo类型的节俭介绍由下式表示B。尽管*D.Foo有Read()方法,但Foo别名没有。这就是为什么您看到错误消息的原因。错误消息在您的情况下令人困惑,因为在错误文本中Foo含糊不清地引用D.Foo或节俭别名–编译器表示其中一个,而您将其解释为另一个。
您可以通过写(*D.Foo)(b.X).Read()或在复制情况下将值转换为正确的类型来遍历别名:
package main
type A struct{}
type B *A
func (a *A) Read() {}
func main() {
var b B
(*A)(b).Read()
}
Run Code Online (Sandbox Code Playgroud)
正如 @Anyonymous 指出的,这是 thrift 别名和使用错误别名的问题。我认为这是 Thrift 编译器(0.9.2 和当前 HEAD 中)的一个错误,因为它会生成永远无法工作的代码。我们在使用其他语言时没有遇到这个问题,就去吧。这是重现该问题的简化:
// Base.thrift
namespace go a.X.c
struct Foo {
1: required string s
}
Run Code Online (Sandbox Code Playgroud)
和依赖文件
// Child.thrift
namespace go a.Y.c
include "Base.thrift"
typedef Base.Foo Foo // <---- This is what causes the problem
struct Bar {
1:Foo f // <-- Will error
// 1:Base.Foo f Need to comment out typedef and use this instead
}
Run Code Online (Sandbox Code Playgroud)
按原样编译 thrift 就可以了,但是当你安装该a.Y.c包时会产生:
/scratch/go/src/a/Y/c/ttypes.go:78: cannot use c.Foo literal (type *c.Foo) as type *Foo in assignment
/scratch/go/src/a/Y/c/ttypes.go:79: p.F.Read undefined (type *Foo has no field or method Read)
/scratch/go/src/a/Y/c/ttypes.go:105: p.F.Write undefined (type *Foo has no field or method Write)
Run Code Online (Sandbox Code Playgroud)
如果我注释掉 typedef 并交换行,Bar那么一切都会正常。这似乎只发生在 Go 中。
| 归档时间: |
|
| 查看次数: |
8806 次 |
| 最近记录: |