Not so familiar with Golang, it's probably a stupid mistake I made... But still, I can't for the life of me figure it out.
So, I got a proto3 file (let's call it file.proto), whose header is as follows:
syntax = "proto3";
package [package_name];
option go_package = "github.com/[user]/[repository]";
And I use protoc:
protoc --go_out=$GOPATH/src --go-grpc_out=$GOPATH/src file.proto
So far so good, I end up with two generated files (file.pb.go and file_grpc.pb.go) inside /go/src/github.com/[user]/[repository]/, and they are defined inside the package [package_name].
Then, the code I'm trying to build has the following import:
import (
"github.com/[user]/[repository]/[package_name]"
)
And I naively thought it would work. However, it produces the following error when running go mod tidy:
go: downloading github.com/[user]/[repository] v0.0.0-20211105185458-d7aab96b7629
go: finding module for package github.com/[user]/[repository]/[package_name]
example/xxx imports
github.com/[user]/[repository]/[package_name]: module github.com/[user]/[repository]@latest found (v0.0.0-20211105185458-d7aab96b7629), but does not contain package github.com/[user]/[repository]/[package_name]
Any idea what I'm doing wrong here? Go version is go1.19 linux/amd64 within Docker (golang:1.19-alpine).
Note: I also tried to only import github.com/[user]/[repository], same issue obviously.
UPDATE:
OK so what I do is that I get the proto file from the git repository that only contains the proto file:
wget https://raw.githubusercontent.com/[user]/[repository]/file.proto
Then I generate go files from that file with protoc:
protoc --go_out=. --go-grpc_out=. file.proto
Right now, in current directory, it looks like:
- directory
| - process.go
| - file.proto
| - github.com
| - [user]
| - [repository]
| - file.pb.go
| - file_grpc.pb.go
In that same directory, I run:
go mod init xxx
go mod tidy
CGO_ENABLED=0 go build process.go
The import directive in process.go is as follows:
import (
"xxx/github.com/[user]/[repository]"
)
Now it looks like it finds it, but still getting a gRPC error, which is weird because nothing changed. I still have to figure out if it comes from the issue above or not. Thanks!
Your question is really a number of questions in one; I'll try to provide some info that will help. The initial issue you had was because
This makes sense because importing
github.com/[user]/[repository]would be fairly pointless if that repository does not contain any.gofiles (i.e. the go compiler could not really do anything with the files).Your options are:
protocdirectly into your project folder and change thepackagedeclarations to match your package. If you do this there is no need for any imports.go_outargument toprotoc) the output fromprotocinto a subfolder of your project. The import path will then be the value of themoduledeclaration in yourgo.modplus the path from the folder that thego.modis in (this is what you have done)..protofiles if you "want it to be agnostic" (note that 2 & 3 can be combined if the generated files will only be used within one code base or the repo is accessible to all users).Option 1 is simple but its often beneficial to keep the generated code separate (makes it clear what you should not edit and improves editor autocomplete etc).
Option 2 is OK (especially if
protocwrites the files directly and you setgo_packageappropriately). However issues may arise when the generated files will be used in multiple modules (e.g. as part of your customers code) and your repo is private. They will need to changego_packagebefore runningprotoc(or search/replace thepackagedeclarations) and importing other.protofiles may not work well.Option 3 is probably the best approach in most situations because this works with the go tooling. You can create
github.com/[user]/goproto(or similar) and put all of your generated code in there. To use this your customers just need toimport github.com/[user]/goproto(no need to runprotocetc).Go Modules/package intro
The go spec does not detail the format of import paths, leaving it up to the implementation:
As you are using go modules (pretty much the default now) the implementations rules for resolving package paths (synonym of import path) can be summarised as:
So if your "module path" (generally the top line in a
go.mod) is set toxxx(go mod init xxx) then you would import the package in subfoldergithub.com/[user]/[repository]withimport xxx/github.com/[user]/[repository](as you have found). If you got rid of the intervening folders and put the files into the[repository]subfolder (directly off your main folder) then it would beimport xxx/[repository]You will note in the examples above that the
modulenames I used are paths to repo (as opposed to thexxxyou used ingo mod init xxx). This is intentional because it allows the go tooling to find the package when you import it from a different module. For example if you had usedgo mod init github.com/[user]/[repository]andoption go_package = "github.com/[user]/[repository]/myproto";"then the generated files should go into themyprotofolder in your project and you import them withimport github.com/[user]/[repository]/myproto.While you do not have to follow this approach I'd highly recommend it (it will save you from a lot of pain!). It can take a while to understand the go way of doing this, but once you do, it works well and makes it very clear where a package is hosted.