protoc-生成go指针 protoc-生成go指针

protoc-生成go指针

这里指的是为结构体中基础类型生成go指针,嵌套结构体默认就是指针

为什么需要生成指针?

  因为在一些场景中指针表示的含义是比类型表示的多的

type user struct {
    name    string
    address string
}

假设上述结构体表示一个用户的信息,创建用户后希望更新用户名时该怎么实现?这里隐藏的一个问题就是:address为空字符串时,到底是表示不更新该字段?还是表示将该字段置为空?

type user struct {
    name    string
    address *string
}

使用指针的意义就是该字段可以额外表示一重含义

  • address字段可以为空字符串
  • address字段可以为非空字符串
  • address字段可以直接为nil,表示该字段无效

proto3生成指针的方法

proto2的结构体字段除了repeated外默认就是指针,不过多说明了

protoclibprotoc 3.17.3

protoc-gen-go1.5.2

optional关键字

proto3最开始去掉了optional字段,但是后续又加回来了

syntax = "proto3";

package exp;

option go_package = "./go";


message T {
    optional int32 intPtr = 1;
}
protoc --go_out=./ exp.proto

optional对于protocprotoc-gen-go的版本都是有依赖的,在低版本中还需要带上额外字段

protoc --experimental_allow_proto3_optional --go_out=./ exp.proto

[需要带上--experimental_allow_proto3_optional](protocol buffers - How to define an optional field in protobuf 3 - Stack Overflow)

gogo/protobuf

gogo/protobuf是在protobuf基础上开发出来的一些工具,支持一些扩展语法之类的,使用也是比较广泛的

使用上面同样的protoc文件,发现是无法支持的

protoc --gofast_out=./ exp.proto
exp.proto: is a proto3 file that contains optional fields, but code generator protoc-gen-gofast hasn't been updated to support optional fields in proto3. Please ask the owner of this code generator to support proto3 optional.--gofast_out:

gogo/protobuf还未支持optional的语法,一种可行的解法就是在proto3中导入proto2的文件,并且把需要定义为指针的字段放在proto2

wktpointer扩展语法

syntax = "proto3";

package exp;

import "google/protobuf/wrappers.proto";
import "github.com/gogo/[email protected]/gogoproto/gogo.proto";

option go_package = "./go";


message T {
    google.protobuf.Int32Value intPtr = 1 [(gogoproto.wktpointer) = true];
}
type T struct {
    IntPtr               *int32   `protobuf:"bytes,1,opt,name=intPtr,proto3,wktptr" json:"intPtr,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}

不过在网络上很难找到wktptr的介绍,这个语法也非常让人困惑

nullable

syntax = "proto3";

package exp;

//import "google/protobuf/wrappers.proto";
import "github.com/gogo/[email protected]/gogoproto/gogo.proto";

option go_package = "./go";


message T {
    int32 intPtr = 1 [(gogoproto.nullable) = false];
}
ERROR: field T.IntPtr is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values--gofast_out: protoc-gen-gofast: Plugin failed with status code 1.

nullable扩展字段无法支持原生类型,此扩展字段对此是无效的

  

embed

最简单的方法就是通过import的方式在proto3中加载proto2的语法,但是实际上通过内嵌结构体的方式来优化一下

message T {
    S s = 1 [(gogoproto.embed)=true];
}

这样可以将需要定义为指针的元素定义到proto2中然后内嵌进来

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章