我很难过这个。在我正在进行的项目中,我们从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)
我查看了其中一条有问题的行:
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 {
...
}
由于我使用的是IntelliJ,因此我按CTRL +点击了Read()
方法,确定它跳转到$GOPATH/A/B/D/ttypes.go
方法
func (p *Foo) Read(iprot thrift.TProtocol) error {
...
}
这正是我期望该方法所在的文件,它是指向Foo
的指针的方法,所以没有问题。一切似乎都应该是正确的,但是在IntelliJ和命令行中我都遇到了这些问题。
任何想法可能会出错?当它告诉我方法不存在时会感到沮丧,但如果我点击它(并且还会在智能感知中弹出),它会让我感到沮丧
编辑 - 每条评论
type Bar struct {
X Foo `thrift:"x,1,required"`
}
答案 0 :(得分:4)
这是你所看到的最小复制品。
package main
type A struct{}
type B *A
func (a *A) Read() {}
func main() {
var b B
b.Read()
}
编译会产生以下错误消息:
prog.go:11: b.Read undefined (type B has no field or method Read)
问题在于,节俭正在定义它自己的Foo
*D.Foo
,这就是b.X
的类型。 D.Foo
类型在我的代码中由A
表示,而thrift引入的Foo
类型由B
表示。虽然*D.Foo
具有Read()
方法,但Foo
别名却没有。这就是你看到错误信息的原因。在您的情况下,错误消息令人困惑,因为Foo
模糊地引用了D.Foo
或错误文本中的thrift别名 - 编译器意味着其中之一,并且您将其解释为意味着其他
您可以通过编写(*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()
}
答案 1 :(得分:0)
请不要拒绝投票,但我想表达一个简单的代码来重现您可能遇到的情况。 (我没有使用Thrift的经验,但我认为它与包有更多关系)
package main
import (
"fmt"
"D"
)
type Foo struct {}
func (f *Foo) PrintIt() {
fmt.Println("Sample printing")
}
type Bar struct {
// For the sake of this experiment
X *D.Foo
}
func (b *Bar) PrintFromBar() {
// simulates b.x = D.NewFoo()
b.X = new(D.Foo)
b.X.PrintIt() // The culprit happens here
}
func main() {
b := new(Bar)
b.PrintFromBar()
}
D包:
package D
type Foo struct {}
b.PrintFromBar()
以" b.X.PrintIt未定义(类型* D.Foo没有字段或方法PrintIt)失败。
问题可能出在D.NewFoo()
为Foo
创建名为*D.Foo
的别名。在你的情况下,由于你的Read()
方法已经在D包中,我不知道没有完整的代码。然而,有趣的是,这实际上会产生相同的错误。
答案 2 :(得分:0)
正如@Anyonymous所指出的,这是thrift别名和使用错误的问题。我认为这是Thrift编译器(在0.9.2和当前的HEAD中)中的一个错误,因为它将生成永远不会工作的代码。我们还没有遇到其他语言的问题,只是去吧。以下是重现问题的简化:
// Base.thrift
namespace go a.X.c
struct Foo {
1: required string s
}
和依赖文件
// 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
}
按原样编译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)
如果我注释掉typedef并交换Bar
中的行,那么一切正常。这似乎只发生在Go。