goprotocol-buffersgrpcimporterrorprotobuf-go

Protobuf generated file doesn't recognize import path


I have a proto file product.proto and I want to use it in catalog.proto. I can successfully import product.proto in catalog.proto but auto-generated catalog.pb.go is not able to reconize the path of its dependency i.e. product.pb.go. It states:

could not import catalog/pb/entities (cannot find package "catalog/pb/entities" in any of /usr/local/go/src/catalog/pb/entities (from $GOROOT)
/Users/trimulabs/go/src/catalog/pb/entities (from $GOPATH))

Directory structure

📦catalog
 ┣ 📂main
 ┃ ┣ 📜client.go
 ┃ ┗ 📜server.go
 ┣ 📂pb
 ┃ ┣ 📂entities
 ┃ ┃ ┣ 📜product.pb.go
 ┃ ┃ ┗ 📜product.proto
 ┃ ┣ 📜catalog.pb.go
 ┃ ┗ 📜catalog.proto

catalog.proto

syntax = "proto3";
package catalog;
import "catalog/pb/entities/product.proto";

service CatalogService {
    rpc PostProduct (PostProductRequest) returns (PostProductResponse) {}
    rpc GetProduct (GetProductRequest) returns (GetProductResponse) {}
    rpc GetProducts (GetProductsRequest) returns (GetProductsResponse) {}
}

product.proto

message Product {
    string id = 1;
    string name = 2;
    string description = 3;
    double price = 4;
}
message PostProductRequest {
    string name = 1;
    string description = 2;
    double price = 3;
}
message PostProductResponse {
    Product product = 1;
}

message GetProductRequest {
    string id = 1;
}

message GetProductResponse {
    Product product = 1;
}

message GetProductsRequest {
    uint64 skip = 1;
    uint64 take = 2;
    repeated string ids = 3;
    string query = 4;
}

message GetProductsResponse {
    repeated Product products = 1;
}

Can anyone please help?


Solution

  • The error you are seeing is caused because your generated protobuf file likely has an incorrect import path.

    If you check your product.pb.go file, it likely has a like like:

    import "catalog/pb/entities"
    

    This means it is trying to import the go package with that specified path. As you are probably familiar with, a go package must use the absolute path, so this needs to look something like:

    import "github.com/<myuser>/<myproject>/catalog/pb/entities"
    

    protoc-gen-go fortunately supports a couple of flags to help you with this.

    Step 1. Set go_package in your .proto file to specify the anticipated import path in go.

    option go_package = "example.com/foo/bar";
    

    Step 2: use the --go_opt=module=github.com/<myuser>/<project> flag of protoc to strip the module prefix from your generated code. Otherwise you would get something like this as an output (assuming you are using the current directory as your go_out path

    catalog/
      main/
      pb/
      github.com/
        <myuser>/
          <project>/
            catalog/
              pb/
                entities/
    

    I would recommend reviewing the documentation page on the protoc-gen-go go flags: