goprotocol-buffersprotoprotobuf-goprotoreflect

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!


Solution

  • 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.