Protocol buffers in Go: cannot find package

huangapple go评论84阅读模式
英文:

Protocol buffers in Go: cannot find package

问题

我正在按照Go语言的Protocol Buffer教程进行操作,但是遇到了以下问题:

  1. 我创建了addressbook的proto定义:
syntax = "proto3";
package tutorial;

message Person {
  string name = 1;
  ...
}
  1. 我成功地运行了编译器并生成了Go代码。
  2. 我尝试导入pb包,但是失败了。

具体情况如下:我将--go_out参数设置为与我的proto定义相同的目录(protoc --go_out=. addressbook.proto),然后在同一个目录下创建了一个test.go文件,内容如下:

package main

import "tutorial"

但是运行go build test.go时返回错误:

test.go:3:8: cannot find package "tutorial" in any of:
        /usr/local/go/src/tutorial (from $GOROOT)
        /home/vagrant/go2/src/tutorial (from $GOPATH)

然后我将test.go修改为:

package main

import "protobufs/tutorial"

但是又出现了以下错误:

test.go:3:8: cannot find package "protobufs/tutorial" in any of:
        /usr/local/go/src/protobufs/tutorial (from $GOROOT)
        /home/vagrant/go2/src/protobufs/tutorial (from $GOPATH)

但是如果我将导入语句修改为:

package main

import "protobufs"

它会发现在该位置有一个名为"tutorial"的包:

test.go:3:8: found packages tutorial (addressbook.pb.go) and main (list_people.go) in /home/vagrant/go2/src/protobufs

我做错了什么?为了使其工作,导入语句应该是什么样的?

谢谢!

我的go env的一部分信息如下:

GOARCH="amd64"
GOBIN="/home/vagrant/go2/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/vagrant/go2"
GORACE=""
GOROOT="/usr/local/go"
英文:

I'm following the Protocol Buffer for Go tutorial but I have the following problem:

  1. I create the addressbook proto definition

> syntax = "proto3";
> package tutorial;
>
> message Person {
> string name = 1;
> ...
> }

  1. I successfully run the compiler and generate the go code
  2. I try to import the pb package but it fails

Here is exactly what happens: I specifying the --go_out to be same as my proto definition: (protoc --go_out=. addressbook.proto)

then in same folder, I create a test.go with these simple lines:

package main

import "tutorial"

but go build test.go returns error:

test.go:3:8: cannot find package "tutorial" in any of:
    /usr/local/go/src/tutorial (from $GOROOT)
    /home/vagrant/go2/src/tutorial (from $GOPATH)

then I change test.go to this:

package main

import "protobufs/tutorial"

and get this error:

test.go:3:8: cannot find package "protobufs/tutorial" in any of:
    /usr/local/go/src/protobufs/tutorial (from $GOROOT)
    /home/vagrant/go2/src/protobufs/tutorial (from $GOPATH)

but if I change the import to only:

package main

import "protobufs"

it finds that there's a "tutorial" package in that location:

test.go:3:8: found packages tutorial (addressbook.pb.go) and main (list_people.go) in /home/vagrant/go2/src/protobufs

What am I doing wrong ? How should the import look like in order to make this work ?

Thank you !

FYI: a snippet of my go env:

GOARCH="amd64"
GOBIN="/home/vagrant/go2/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/vagrant/go2"
GORACE=""
GOROOT="/usr/local/go"

答案1

得分: 2

这个问题显示了我对Go语言的包管理机制的理解不足。经过一些阅读,我得出了以下结论/规则:

  1. 每个文件夹对应一个包:文件夹"abc"中的所有.go文件将指定为package abc
  2. 不能在同一个文件夹中同时存在main包和abc包。
  3. go install命令会在$GOPATH/pkg/GOOS_GOARCH/<path_to_abc_excluding_abc>目录下创建包对象abc.a
  4. 对于位于$GOPATH/src/x/y/z/foo/文件夹中的main包,go install命令会编译并安装一个名为foo(路径中最后一个目录的名称)的可执行文件到$GOPATH/bin目录中。

现在,回到最初的问题:目录$GOPATH/src/protobufs包含多个包:

  • 编译后的protobuf包名为tutorial
  • test.go中的main包。
    这与上述列出的规则相矛盾。

我认为一个优雅的解决方案是:

  • 假设我在$GOPATH/src/protobufs目录下,
  • 创建一个名为tutorials的子目录,
  • 将编译后的protobuf安装到该子目录中:protoc --go_out=./tutorial ./addressbook.proto
  • 现在,test.go可以使用package mainimport "protobufs/tutorial"

感谢你将我引导到正确的方向!

英文:

This question showed my lack of understanding of Go's packaging. After some reading, here are my conclusions/rules:

  1. one package per folder: all the .go files in directory "abc" will indicate package abc
  2. you can't have package main and package abc in same folder
  3. go install creates package object abc.a in $GOPATH/pkg/GOOS_GOARCH/&lt;path_to_abc_excluding_abc&gt;
  4. for the package main in folder $GOPATH/src/x/y/z/foo/ then go install compiles and installs an executable called foo (the name of the last directory in the path) in $GOPATH/bin

Now, back to the initial question: the directory $GOPATH/src/protobufs contains multiple packages:

  • the compiled protobuf with the package name tutorial and
  • the main package in test.go
    This contradicts with the above listed rules.

I believe that one elegant solution is:

  • assuming I'm in $GOPATH/src/protobufs
  • create a subdir called tutorials
  • install the compiled protobuf in that subdir: protoc --go_out=./tutorial ./addressbook.proto
  • the test.go can now have package main and import &quot;protobufs/tutorial&quot;

Thanks for putting on the right track !

答案2

得分: 0

查看Go工作区

工作区是一个目录层次结构,其根目录下有两个目录:

src:包含Go源文件
bin:包含可执行命令

本教程基于这个结构,即:

src/
    github.com/protocolbuffers/protobuf/examples/
      tutorial/
         addressbook.pb.go
      list_address.go

在该教程的makefile中,通过以下方式在examples目录下生成pb.go

mkdir -p tutorial
protoc $$PROTO_PATH --go_out=tutorial addressbook.proto

add_person.go中,它假设导入路径在workspace/src下,即上面提到的$GOPATH/src

import (
....

pb "github.com/protocolbuffers/protobuf/examples/tutorial"
// 可以通过 $GOPATH/src/github.com/protocolbuffers/protobuf/examples/tutorial 找到
)

你需要做的是设置正确的GOPATH并在$GOPATH/src下生成pb.go

protoc -I=. --go_out=/Users/guihaoliang/Playground/go/my_workspace/src addressbook.proto

其中.表示addressbook.proto所在的位置。

GOPATH工作区将被go modules取代,这样你就不必维护srcbin结构。protobuf示例不使用新的模块结构。

英文:

check GO workspace:

A workspace is a directory hierarchy with two directories at its root:

src contains Go source files, and
bin contains executable commands.

The tutorial is based on this structure, i.e.,

src/
    github.com/protocolbuffers/protobuf/examples/
      tutorial/
         addressbook.pb.go
      list_address.go

In the makefile of that tutorial, it generates pb.go under examples dir through:

mkdir -p tutorial
protoc $$PROTO_PATH --go_out=tutorial addressbook.proto

Under the add_person.go, it just assumes the import path is under worksapce/src, which is $GOPATH/src mentioned above:

import (
....

pb &quot;github.com/protocolbuffers/protobuf/examples/tutorial&quot;
// find through $GOPATH/src/github.com/protocolbuffers/protobuf/examples/tutorial
)

What you need to do is to set the right GOPATH and generate that pb.go under $GOPATH/src

protoc -I=. --go_out=/Users/guihaoliang/Playground/go/my_workspace/src addressbook.proto

where . refers to where the addressbook.proto is located.

The GOPATH workspace is going to be superseded by go modules so that you don't have to maintain the src and bin structure. The protobuf example is not using the new module structure.

huangapple
  • 本文由 发表于 2017年5月6日 07:36:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/43815108.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定