原型布夫教程:"AddressBook does not implement " github.com/gogo/protobuf/proto ".Message (ProtoMessage meth



我正在尝试按照ProtoBufs上的本教程进行操作:https://developers.google.com/protocol-buffers/docs/gotutorial。我有以下项目结构:

.
├── addressbook
│   ├── addressbook.pb.go
│   └── addressbook.proto
├── go.mod
├── go.sum
└── main.go

addressbook.proto在哪里

syntax = "proto3";
package addressbook;
import "google/protobuf/timestamp.proto";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
google.protobuf.Timestamp last_updated = 5;
}
message AddressBook {
repeated Person people = 1;
}

和自动生成的(带protoc addressbook.proto --go-out=.(addressbook.pb.go读取

// Code generated by protoc-gen-go. DO NOT EDIT.
// source: addressbook.proto
package addressbook
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
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 Person_PhoneType int32
const (
Person_MOBILE Person_PhoneType = 0
Person_HOME   Person_PhoneType = 1
Person_WORK   Person_PhoneType = 2
)
var Person_PhoneType_name = map[int32]string{
0: "MOBILE",
1: "HOME",
2: "WORK",
}
var Person_PhoneType_value = map[string]int32{
"MOBILE": 0,
"HOME":   1,
"WORK":   2,
}
func (x Person_PhoneType) String() string {
return proto.EnumName(Person_PhoneType_name, int32(x))
}
func (Person_PhoneType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_1eb1a68c9dd6d429, []int{0, 0}
}
type Person 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"`
Email                string                `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
Phones               []*Person_PhoneNumber `protobuf:"bytes,4,rep,name=phones,proto3" json:"phones,omitempty"`
LastUpdated          *timestamp.Timestamp  `protobuf:"bytes,5,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"`
XXX_NoUnkeyedLiteral struct{}              `json:"-"`
XXX_unrecognized     []byte                `json:"-"`
XXX_sizecache        int32                 `json:"-"`
}
func (m *Person) Reset()         { *m = Person{} }
func (m *Person) String() string { return proto.CompactTextString(m) }
func (*Person) ProtoMessage()    {}
func (*Person) Descriptor() ([]byte, []int) {
return fileDescriptor_1eb1a68c9dd6d429, []int{0}
}
func (m *Person) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Person.Unmarshal(m, b)
}
func (m *Person) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Person.Marshal(b, m, deterministic)
}
func (m *Person) XXX_Merge(src proto.Message) {
xxx_messageInfo_Person.Merge(m, src)
}
func (m *Person) XXX_Size() int {
return xxx_messageInfo_Person.Size(m)
}
func (m *Person) XXX_DiscardUnknown() {
xxx_messageInfo_Person.DiscardUnknown(m)
}
var xxx_messageInfo_Person proto.InternalMessageInfo
func (m *Person) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *Person) GetId() int32 {
if m != nil {
return m.Id
}
return 0
}
func (m *Person) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *Person) GetPhones() []*Person_PhoneNumber {
if m != nil {
return m.Phones
}
return nil
}
func (m *Person) GetLastUpdated() *timestamp.Timestamp {
if m != nil {
return m.LastUpdated
}
return nil
}
type Person_PhoneNumber struct {
Number               string           `protobuf:"bytes,1,opt,name=number,proto3" json:"number,omitempty"`
Type                 Person_PhoneType `protobuf:"varint,2,opt,name=type,proto3,enum=addressbook.Person_PhoneType" json:"type,omitempty"`
XXX_NoUnkeyedLiteral struct{}         `json:"-"`
XXX_unrecognized     []byte           `json:"-"`
XXX_sizecache        int32            `json:"-"`
}
func (m *Person_PhoneNumber) Reset()         { *m = Person_PhoneNumber{} }
func (m *Person_PhoneNumber) String() string { return proto.CompactTextString(m) }
func (*Person_PhoneNumber) ProtoMessage()    {}
func (*Person_PhoneNumber) Descriptor() ([]byte, []int) {
return fileDescriptor_1eb1a68c9dd6d429, []int{0, 0}
}
func (m *Person_PhoneNumber) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Person_PhoneNumber.Unmarshal(m, b)
}
func (m *Person_PhoneNumber) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Person_PhoneNumber.Marshal(b, m, deterministic)
}
func (m *Person_PhoneNumber) XXX_Merge(src proto.Message) {
xxx_messageInfo_Person_PhoneNumber.Merge(m, src)
}
func (m *Person_PhoneNumber) XXX_Size() int {
return xxx_messageInfo_Person_PhoneNumber.Size(m)
}
func (m *Person_PhoneNumber) XXX_DiscardUnknown() {
xxx_messageInfo_Person_PhoneNumber.DiscardUnknown(m)
}
var xxx_messageInfo_Person_PhoneNumber proto.InternalMessageInfo
func (m *Person_PhoneNumber) GetNumber() string {
if m != nil {
return m.Number
}
return ""
}
func (m *Person_PhoneNumber) GetType() Person_PhoneType {
if m != nil {
return m.Type
}
return Person_MOBILE
}
type AddressBook struct {
People               []*Person `protobuf:"bytes,1,rep,name=people,proto3" json:"people,omitempty"`
XXX_NoUnkeyedLiteral struct{}  `json:"-"`
XXX_unrecognized     []byte    `json:"-"`
XXX_sizecache        int32     `json:"-"`
}
func (m *AddressBook) Reset()         { *m = AddressBook{} }
func (m *AddressBook) String() string { return proto.CompactTextString(m) }
func (*AddressBook) ProtoMessage()    {}
func (*AddressBook) Descriptor() ([]byte, []int) {
return fileDescriptor_1eb1a68c9dd6d429, []int{1}
}
func (m *AddressBook) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AddressBook.Unmarshal(m, b)
}
func (m *AddressBook) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AddressBook.Marshal(b, m, deterministic)
}
func (m *AddressBook) XXX_Merge(src proto.Message) {
xxx_messageInfo_AddressBook.Merge(m, src)
}
func (m *AddressBook) XXX_Size() int {
return xxx_messageInfo_AddressBook.Size(m)
}
func (m *AddressBook) XXX_DiscardUnknown() {
xxx_messageInfo_AddressBook.DiscardUnknown(m)
}
var xxx_messageInfo_AddressBook proto.InternalMessageInfo
func (m *AddressBook) GetPeople() []*Person {
if m != nil {
return m.People
}
return nil
}
func init() {
proto.RegisterEnum("addressbook.Person_PhoneType", Person_PhoneType_name, Person_PhoneType_value)
proto.RegisterType((*Person)(nil), "addressbook.Person")
proto.RegisterType((*Person_PhoneNumber)(nil), "addressbook.Person.PhoneNumber")
proto.RegisterType((*AddressBook)(nil), "addressbook.AddressBook")
}
func init() { proto.RegisterFile("addressbook.proto", fileDescriptor_1eb1a68c9dd6d429) }
var fileDescriptor_1eb1a68c9dd6d429 = []byte{
// 309 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0x41, 0x4b, 0xc3, 0x40,
0x10, 0x85, 0x4d, 0x9a, 0x06, 0x3b, 0x91, 0x52, 0x47, 0x91, 0x50, 0x90, 0x86, 0x9e, 0x02, 0x85,
0x14, 0xeb, 0x41, 0x10, 0x3c, 0x58, 0x28, 0x28, 0x5a, 0x5b, 0x96, 0x8a, 0xde, 0x24, 0x21, 0x63,
0x0d, 0x4d, 0xb2, 0x4b, 0x76, 0x7b, 0xe8, 0xcf, 0xf3, 0x9f, 0x49, 0x76, 0x53, 0xe9, 0x41, 0x6f,
0x6f, 0x66, 0x3f, 0xde, 0xbe, 0x37, 0x70, 0x1a, 0xa7, 0x69, 0x45, 0x52, 0x26, 0x9c, 0x6f, 0x22,
0x51, 0x71, 0xc5, 0xd1, 0x3b, 0x58, 0xf5, 0x07, 0x6b, 0xce, 0xd7, 0x39, 0x8d, 0xf5, 0x53, 0xb2,
0xfd, 0x1c, 0xab, 0xac, 0x20, 0xa9, 0xe2, 0x42, 0x18, 0x7a, 0xf8, 0x6d, 0x83, 0xbb, 0xa4, 0x4a,
0xf2, 0x12, 0x11, 0x9c, 0x32, 0x2e, 0xc8, 0xb7, 0x02, 0x2b, 0xec, 0x30, 0xad, 0xb1, 0x0b, 0x76,
0x96, 0xfa, 0x76, 0x60, 0x85, 0x6d, 0x66, 0x67, 0x29, 0x9e, 0x43, 0x9b, 0x8a, 0x38, 0xcb, 0xfd,
0x96, 0x86, 0xcc, 0x80, 0x37, 0xe0, 0x8a, 0x2f, 0x5e, 0x92, 0xf4, 0x9d, 0xa0, 0x15, 0x7a, 0x93,
0x41, 0x74, 0x18, 0xcb, 0xd8, 0x47, 0xcb, 0x9a, 0x78, 0xd9, 0x16, 0x09, 0x55, 0xac, 0xc1, 0xf1,
0x0e, 0x4e, 0xf2, 0x58, 0xaa, 0x8f, 0xad, 0x48, 0x63, 0x45, 0xa9, 0xdf, 0x0e, 0xac, 0xd0, 0x9b,
0xf4, 0x23, 0x93, 0x3a, 0xda, 0xa7, 0x8e, 0x56, 0xfb, 0xd4, 0xcc, 0xab, 0xf9, 0x57, 0x83, 0xf7,
0xdf, 0xc1, 0x3b, 0x70, 0xc5, 0x0b, 0x70, 0x4b, 0xad, 0x9a, 0x0a, 0xcd, 0x84, 0x57, 0xe0, 0xa8,
0x9d, 0x20, 0x5d, 0xa3, 0x3b, 0xb9, 0xfc, 0x37, 0xdc, 0x6a, 0x27, 0x88, 0x69, 0x74, 0x38, 0x82,
0xce, 0xef, 0x0a, 0x01, 0xdc, 0xf9, 0x62, 0xfa, 0xf8, 0x3c, 0xeb, 0x1d, 0xe1, 0x31, 0x38, 0x0f,
0x8b, 0xf9, 0xac, 0x67, 0xd5, 0xea, 0x6d, 0xc1, 0x9e, 0x7a, 0xf6, 0xf0, 0x16, 0xbc, 0x7b, 0x63,
0x39, 0xe5, 0x7c, 0x83, 0x23, 0x70, 0x05, 0x71, 0x91, 0xd7, 0x97, 0xac, 0xaf, 0x71, 0xf6, 0xc7,
0x87, 0xac, 0x41, 0x12, 0x57, 0x77, 0xbc, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0x9a, 0x92, 0x62,
0x76, 0xc9, 0x01, 0x00, 0x00,
}

我正在main.go尝试这个脚本:

package main
import (
"fmt"
"github.com/gogo/protobuf/proto"
"github.com/kurtpeek/addressbook/addressbook"
"github.com/sirupsen/logrus"
)
func main() {
person := addressbook.Person{
Name:  "Boba Fett",
Email: "boba.fett@gmail.com",
Phones: []*addressbook.Person_PhoneNumber{
&addressbook.Person_PhoneNumber{
Number: "4158666171",
Type:   addressbook.Person_MOBILE,
},
},
}
book := addressbook.AddressBook{
People: []*addressbook.Person{&person},
}
_, err := proto.Marshal(book)
if err != nil {
logrus.WithError(err).Fatal("marshal to ProtoBuf")
}
fmt.Printf("%+vn", person)
}

问题是当我尝试运行它时,我收到一个错误,AddressBook没有实现Message接口:

> go run main.go
# command-line-arguments
./main.go:26:25: cannot use book (type addressbook.AddressBook) as type "github.com/gogo/protobuf/proto".Message in argument to "github.com/gogo/protobuf/proto".Marshal:
addressbook.AddressBook does not implement "github.com/gogo/protobuf/proto".Message (ProtoMessage method has pointer receiver)

转到Message的定义,我找到以下接口:

// Message is implemented by generated protocol buffer messages.
type Message interface {
Reset()
String() string
ProtoMessage()
}

addressbook.pg.go看来,AddressBook实现了所有这三种方法,所以我不明白为什么我会收到错误消息?

这是我的go.mod

module github.com/kurtpeek/addressbook
go 1.12
require (
github.com/gogo/protobuf v1.3.1
github.com/golang/protobuf v1.3.2
github.com/sirupsen/logrus v1.4.2
)

这是我的protoc版本(我使用brew install protobuf安装了protoc(:

> protoc --version
libprotoc 3.11.1

你需要传递一个指向 proto 的指针。Marshal(( 要么做proto.Marshal(&book),要么在创建指针之前创建指针,就像这样创建书籍:

book := &addressbook.AddressBook{
People: []*addressbook.Person{&person},
}

请参阅第一行中的 &

这是API 版本的问题。

来自 go 博客

github.com/golang/protobuf 模块是 APIv1。google.golang.org/protobuf 模块是 APIv2。我们利用了更改导入路径的需求,以切换到与特定托管服务提供商无关的路径。(我们考虑了 google.golang.org/protobuf/v2,以明确这是API的第二个主要版本,但从长远来看,我们认为较短的路径是更好的选择。

因此,若要简单地运行代码,请使用"github.com/golang/protobuf/proto"而不是"github.com/gogo/protobuf/proto"作为封送函数。问题来自一个新的 api 原型反射。见文章。

您可以选择使用"google.golang.org/protobuf",但我的建议是使用"github.com/golang/protobuf/proto"。您可以在此处阅读有关两者差异的更多信息。

最新更新