ProtoBuf教程:“文件”;通讯录不执行“通讯录”;github.com/gogo/protobuf/proto";。消息(ProtoMessage方法具有指针接收器)";

ProtoBuf教程:“文件”;通讯录不执行“通讯录”;github.com/gogo/protobuf/proto";。消息(ProtoMessage方法具有指针接收器)";,go,Go,我正试图跟随本教程学习ProtoBufs:。我有以下项目结构: . ├── addressbook │   ├── addressbook.pb.go │   └── addressbook.proto ├── go.mod ├── go.sum └── main.go 其中addressbook.proto是 syntax = "proto3"; package addressbook; import "google/protobuf/timestamp.proto"; message

我正试图跟随本教程学习ProtoBufs:。我有以下项目结构:

.
├── 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("%+v\n", person)
}
问题是,当我尝试运行此操作时,我得到一个错误,即
地址簿
没有实现
消息
接口:

> 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 is implemented by generated protocol buffer messages.
type Message interface {
    Reset()
    String() string
    ProtoMessage()
}
转到
消息的定义
,我发现以下界面:

> 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 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安装protobuf
安装了
protoc
):


您需要传递一个指向proto.Marshal()的指针,或者执行
proto.Marshal(&book)
操作,或者在创建书本时已经创建指针,如下所示:

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

请参阅第一行中的(&p)

您需要传递一个指向proto.Marshal()的指针,或者执行
proto.Marshal(&book)
或者在创建类似于以下内容的书籍时已创建指针:

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

请参阅第一行中的&这是API版本的问题

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 protoreflect。见文章


您可以选择使用“google.golang.org/protobuf”,但我的建议是使用“github.com/golang/protobuf/proto”。您可以阅读更多关于两者区别的信息。

这是API版本的问题

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 protoreflect。见文章

您可以选择使用“google.golang.org/protobuf”,但我的建议是使用“github.com/golang/protobuf/proto”。你可以阅读更多关于两者区别的内容