Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Importing proto files from different package causes 'missing method protoreflect'

I am new to Go and Protobufs hence this might be a very noob question. Sorry for that.

I have several packages in my go project and I wanted to create a seperate package which contains all my .proto (also .pb.go) files and then I can import those proto files in any other packages to better manage all my proto files.

But when I moved my proto files to a seperate package called "prototemps" and imported "prototemps" in another package called "reader". In reader.go, I do:

    sensorData := &prototemps.Sensor{}
    err := proto.Unmarshal(msg.Payload(), sensorData) 

It produces this error

var sensorData *prototemps.Sensor
cannot use sensorData (variable of type *prototemps.Sensor) as protoreflect.ProtoMessage value in argument to proto.Unmarshal: missing method ProtoReflect

Here's how my project structure looks like:

ProjectFolder/
 /prototemps/<all .proto and .pb.go exist here>  (Package "prototemps")
 /reader/reader.go which fails when tries to do proto.Unmarshall (Package "reader")

Here's how my .proto looks like

syntax="proto3";
package prototemps;

import "google/protobuf/timestamp.proto";

message sensor {
      string Name = 1;
      int32 ID = 2;
      string Type = 3;
      orientation Ori = 4;
      IO IO = 5;
      google.protobuf.Timestamp ts = 6;
}

message orientation {
      int32 X = 1;
      int32 Y = 2;
      int32 Z = 3;
}

message IO {
      int32 Reads = 1;
      int32 Writes = 2;
}

Here's my generated .pb.go using *protoc --go_out=. .proto

// Code generated by protoc-gen-go. DO NOT EDIT.
// source: sensorData.proto

package prototemps

import (
    fmt "fmt"
    proto "github.com/golang/protobuf/proto"
    timestamppb "google.golang.org/protobuf/types/known/timestamppb"
    math "math"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package

type Sensor struct {
    Name                 string                 `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
    ID                   int32                  `protobuf:"varint,2,opt,name=ID,proto3" json:"ID,omitempty"`
    Type                 string                 `protobuf:"bytes,3,opt,name=Type,proto3" json:"Type,omitempty"`
    Ori                  *Orientation           `protobuf:"bytes,4,opt,name=Ori,proto3" json:"Ori,omitempty"`
    IO                   *IO                    `protobuf:"bytes,5,opt,name=IO,proto3" json:"IO,omitempty"`
    Ts                   *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=ts,proto3" json:"ts,omitempty"`
    XXX_NoUnkeyedLiteral struct{}               `json:"-"`
    XXX_unrecognized     []byte                 `json:"-"`
    XXX_sizecache        int32                  `json:"-"`
}

func (m *Sensor) Reset()         { *m = Sensor{} }
func (m *Sensor) String() string { return proto.CompactTextString(m) }
func (*Sensor) ProtoMessage()    {}
func (*Sensor) Descriptor() ([]byte, []int) {
    return fileDescriptor_a3adf506f94bdd26, []int{0}
}

func (m *Sensor) XXX_Unmarshal(b []byte) error {
    return xxx_messageInfo_Sensor.Unmarshal(m, b)
}
func (m *Sensor) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
    return xxx_messageInfo_Sensor.Marshal(b, m, deterministic)
}
func (m *Sensor) XXX_Merge(src proto.Message) {
    xxx_messageInfo_Sensor.Merge(m, src)
}
func (m *Sensor) XXX_Size() int {
    return xxx_messageInfo_Sensor.Size(m)
}
func (m *Sensor) XXX_DiscardUnknown() {
    xxx_messageInfo_Sensor.DiscardUnknown(m)
}

var xxx_messageInfo_Sensor proto.InternalMessageInfo

func (m *Sensor) GetName() string {
    if m != nil {
        return m.Name
    }
    return ""
}

func (m *Sensor) GetID() int32 {
    if m != nil {
        return m.ID
    }
    return 0
}

func (m *Sensor) GetType() string {
    if m != nil {
        return m.Type
    }
    return ""
}

func (m *Sensor) GetOri() *Orientation {
    if m != nil {
        return m.Ori
    }
    return nil
}

func (m *Sensor) GetIO() *IO {
    if m != nil {
        return m.IO
    }
    return nil
}

func (m *Sensor) GetTs() *timestamppb.Timestamp {
    if m != nil {
        return m.Ts
    }
    return nil
}

type Orientation struct {
    X                    int32    `protobuf:"varint,1,opt,name=X,proto3" json:"X,omitempty"`
    Y                    int32    `protobuf:"varint,2,opt,name=Y,proto3" json:"Y,omitempty"`
    Z                    int32    `protobuf:"varint,3,opt,name=Z,proto3" json:"Z,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}

func (m *Orientation) Reset()         { *m = Orientation{} }
func (m *Orientation) String() string { return proto.CompactTextString(m) }
func (*Orientation) ProtoMessage()    {}
func (*Orientation) Descriptor() ([]byte, []int) {
    return fileDescriptor_a3adf506f94bdd26, []int{1}
}

func (m *Orientation) XXX_Unmarshal(b []byte) error {
    return xxx_messageInfo_Orientation.Unmarshal(m, b)
}
func (m *Orientation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
    return xxx_messageInfo_Orientation.Marshal(b, m, deterministic)
}
func (m *Orientation) XXX_Merge(src proto.Message) {
    xxx_messageInfo_Orientation.Merge(m, src)
}
func (m *Orientation) XXX_Size() int {
    return xxx_messageInfo_Orientation.Size(m)
}
func (m *Orientation) XXX_DiscardUnknown() {
    xxx_messageInfo_Orientation.DiscardUnknown(m)
}

var xxx_messageInfo_Orientation proto.InternalMessageInfo

func (m *Orientation) GetX() int32 {
    if m != nil {
        return m.X
    }
    return 0
}

func (m *Orientation) GetY() int32 {
    if m != nil {
        return m.Y
    }
    return 0
}

func (m *Orientation) GetZ() int32 {
    if m != nil {
        return m.Z
    }
    return 0
}

type IO struct {
    Reads                int32    `protobuf:"varint,1,opt,name=Reads,proto3" json:"Reads,omitempty"`
    Writes               int32    `protobuf:"varint,2,opt,name=Writes,proto3" json:"Writes,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}

func (m *IO) Reset()         { *m = IO{} }
func (m *IO) String() string { return proto.CompactTextString(m) }
func (*IO) ProtoMessage()    {}
func (*IO) Descriptor() ([]byte, []int) {
    return fileDescriptor_a3adf506f94bdd26, []int{2}
}

func (m *IO) XXX_Unmarshal(b []byte) error {
    return xxx_messageInfo_IO.Unmarshal(m, b)
}
func (m *IO) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
    return xxx_messageInfo_IO.Marshal(b, m, deterministic)
}
func (m *IO) XXX_Merge(src proto.Message) {
    xxx_messageInfo_IO.Merge(m, src)
}
func (m *IO) XXX_Size() int {
    return xxx_messageInfo_IO.Size(m)
}
func (m *IO) XXX_DiscardUnknown() {
    xxx_messageInfo_IO.DiscardUnknown(m)
}

var xxx_messageInfo_IO proto.InternalMessageInfo

func (m *IO) GetReads() int32 {
    if m != nil {
        return m.Reads
    }
    return 0
}

func (m *IO) GetWrites() int32 {
    if m != nil {
        return m.Writes
    }
    return 0
}

func init() {
    proto.RegisterType((*Sensor)(nil), "prototemps.sensor")
    proto.RegisterType((*Orientation)(nil), "prototemps.orientation")
    proto.RegisterType((*IO)(nil), "prototemps.IO")
}

func init() {
    proto.RegisterFile("sensorData.proto", fileDescriptor_a3adf506f94bdd26)
}

var fileDescriptor_a3adf506f94bdd26 = []byte{
    // 259 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0x8e, 0xcf, 0x4a, 0xc3, 0x40,
    0x10, 0xc6, 0xd9, 0xb4, 0x09, 0x38, 0x95, 0x22, 0x83, 0xe8, 0xd2, 0x83, 0x4a, 0x4e, 0xea, 0x61,
    0x0b, 0xf5, 0xe0, 0x0b, 0xf4, 0xd2, 0x8b, 0x81, 0xa5, 0x60, 0xdb, 0xdb, 0x16, 0xd7, 0xb2, 0x60,
    0xb2, 0x61, 0x77, 0x3c, 0xf8, 0x64, 0xbe, 0x9e, 0xfb, 0x27, 0xc5, 0x9c, 0x32, 0xdf, 0xe4, 0x37,
    0xdf, 0xfe, 0xe0, 0xca, 0xeb, 0xce, 0x5b, 0xb7, 0x56, 0xa4, 0x44, 0xef, 0x2c, 0x59, 0x84, 0xf4,
    0x21, 0xdd, 0xf6, 0x7e, 0x71, 0x7f, 0xb2, 0xf6, 0xf4, 0xa5, 0x97, 0x69, 0x75, 0xfc, 0xfe, 0x5c,
    0x92, 0x69, 0xb5, 0x27, 0xd5, 0xf6, 0x19, 0xae, 0x7f, 0x19, 0x54, 0xb9, 0x01, 0x11, 0xa6, 0x6f,
    0xaa, 0xd5, 0x9c, 0x3d, 0xb0, 0xc7, 0x0b, 0x99, 0x66, 0x9c, 0x43, 0xb1, 0x59, 0xf3, 0x22, 0x6c,
    0x4a, 0x19, 0xa6, 0xc8, 0x6c, 0x7f, 0x7a, 0xcd, 0x27, 0x99, 0x89, 0x33, 0x3e, 0xc1, 0xa4, 0x71,
    0x86, 0x4f, 0xc3, 0x6a, 0xb6, 0xba, 0x15, 0xff, 0xaf, 0x0b, 0xeb, 0x8c, 0xee, 0x48, 0x91, 0xb1,
    0x9d, 0x8c, 0x0c, 0xde, 0x85, 0xba, 0x86, 0x97, 0x89, 0x9c, 0x8f, 0xc9, 0x4d, 0x13, 0xea, 0x1b,
    0x7c, 0x86, 0x82, 0x3c, 0xaf, 0xd2, 0xff, 0x85, 0xc8, 0xee, 0xe2, 0xec, 0x2e, 0xb6, 0x67, 0x77,
    0x19, 0xa8, 0xfa, 0x15, 0x66, 0xa3, 0x7e, 0xbc, 0x04, 0xb6, 0x4b, 0xea, 0xa5, 0x64, 0xbb, 0x98,
    0xf6, 0x83, 0x36, 0xdb, 0xc7, 0x74, 0x48, 0xca, 0x21, 0x1d, 0xea, 0x55, 0x94, 0xc0, 0x6b, 0x28,
    0xa5, 0x56, 0x1f, 0x7e, 0xb8, 0xc9, 0x01, 0x6f, 0xa0, 0x7a, 0x77, 0x86, 0xb4, 0x1f, 0x8e, 0x87,
    0x74, 0xac, 0x92, 0xc4, 0xcb, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x7e, 0xde, 0x40, 0x6e,
    0x01, 0x00, 0x00,
}

Any help would be appreciated, Thanks!

like image 369
Ahsan Nasir Avatar asked Jan 04 '21 13:01

Ahsan Nasir


People also ask

What is the difference between Proto file import and fileimports?

FileImport is the declaration for a proto file import. FileImports is a list of file imports. FullName is a qualified name that uniquely identifies a proto declaration.

Why can't I use the same file with protoc?

the build passes successfully, but we can't use the same file with protoc, because the import paths are wrong. and if we import the file like this import "Protos/messages.proto" the build passes on the server but not on the client.

How to convert a proto message to a protoreflect?

To convert a proto.Message to a protoreflect.Message, use the former's ProtoReflect method. Since the ProtoReflect method is new to the v2 message interface, it may not be present on older message implementations. The "github.com/golang/protobuf/proto".MessageReflect function can be used to obtain a reflective view on older messages.

How to import Proto files into Goland?

You must add the path of your proto files to your Goland. for that you must go to setting > Languages & Frameworks > Protocol Buffers then uncheck Configure automatically. After that add this path on import paths. Show activity on this post.


Video Answer


2 Answers

If you're happy with the protoc-gen-go version, you may just want to change your go imports where proto.Unmarshal is called. There are two options I know of:

  • "github.com/golang/protobuf/proto"

  • "google.golang.org/protobuf/proto"

Try the one you don't have. Hope that helps someone else too!

like image 113
DextersLab Avatar answered Oct 10 '22 09:10

DextersLab


The error message says that the variable sensorData is missing a method ProtoReflect. Checking the generated file, this is correct. There is no such method on the Sensor type.

It seems to me you are having issues with different versions of Go's protobuf. Make sure you are using the same version for generating the *.pb.go files as you are using for marshalling / unmarshalling.

There are different packages in the Go world right now that are not compatible as there are breaking API changes: https://blog.golang.org/protobuf-apiv2

If you are starting with protobuf, I'd definitely try to go with the new package. Make sure any introduction you are following uses the package you are using.

like image 20
TehSphinX Avatar answered Oct 10 '22 09:10

TehSphinX