3 Star 9 Fork 5

暖阳 / gogame

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
protobuf转换说明.md 5.03 KB
一键复制 编辑 原始数据 按行查看 历史
wnp 提交于 2022-09-20 14:15 . protobuf转换说明.md 更新

进行protobuf转换的时候需要将bin目录下protoc-gen-go.exe转换为根目录下的protoc-gen-go.exe

原因:

    protobuf本身不支持自定义go的tag,项目中与mongo交互时字段就很不方便,特别是不能指定_id
    所以重新构建了protoc-gen-go.exe
    在定义protobuf文件的时候在注释中加入对应的注释,就能生成对应的tag

例如:

syntax = "proto3";
option go_package = ".;pb";

// 玩家数据
message ModelUser {
	string Id = 1; //@go_tags(`bson:"_id" json:"id" redis:"_id"`)  ID
	string Uid = 2;  //@go_tags(`json:"uid" redis:"uid"`)  玩家uid
	string UUid = 3; //@go_tags(`json:"uuid" redis:"uuid"`)  玩家唯一uuid 根据uid生成
	int64 Sid = 4;  //@go_tags(`json:"sid" redis:"sid"`)  区服id
	string BindUid = 5;  //@go_tags(`json:"binduid" redis:"binduid"`)  玩家账号
	string ExtServerName = 6;  //@go_tags(`json:"extservername" redis:"extservername"`)  区服名
	string Name = 7;  //@go_tags(`json:"name" redis:"name"`)  玩家名
	int64 Ctime = 8;  //@go_tags(`json:"ctime" redis:"ctime"`)  账号创建时间
	int64 LoginTime = 9;  //@go_tags(`json:"logintime" redis:"logintime"`)  最后一次登录时间
	string CreateIp = 10;  //@go_tags(`json:"createip" redis:"createip"`)  创建账号时的id
	string LastLoginIp = 11;  //@go_tags(`json:"lastloginip" redis:"lastloginip"`)  最后一次登录时的ip
}
    
生成后会自动把@go_tags中指定的tag加入到生成的pb.go中
// 玩家数据
type ModelUser struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Id            string `protobuf:"bytes,1,opt,name=Id,proto3" bson:"_id" json:"id" redis:"_id"`                                           // ID
	Uid           string `protobuf:"bytes,2,opt,name=Uid,proto3" redis:"uid" json:"uid" bson:"uid"`                                         // 玩家uid
	UUid          string `protobuf:"bytes,3,opt,name=UUid,proto3" redis:"uuid" json:"uuid" bson:"uuid"`                                     // 玩家唯一uuid 根据uid生成
	Sid           int64  `protobuf:"varint,4,opt,name=Sid,proto3" json:"sid" redis:"sid" bson:"sid"`                                        //  区服id
	BindUid       string `protobuf:"bytes,5,opt,name=BindUid,proto3" redis:"binduid" json:"binduid" bson:"binduid"`                         //  玩家账号
	ExtServerName string `protobuf:"bytes,6,opt,name=ExtServerName,proto3" json:"extservername" redis:"extservername" bson:"extservername"` //  区服名
	Name          string `protobuf:"bytes,7,opt,name=Name,proto3" json:"name" redis:"name" bson:"name"`                                     //  玩家名
	Ctime         int64  `protobuf:"varint,8,opt,name=Ctime,proto3" json:"ctime" redis:"ctime" bson:"ctime"`                                //  账号创建时间
	LoginTime     int64  `protobuf:"varint,9,opt,name=LoginTime,proto3" json:"logintime" redis:"logintime" bson:"logintime"`                //  最后一次登录时间
	CreateIp      string `protobuf:"bytes,10,opt,name=CreateIp,proto3" json:"createip" redis:"createip" bson:"createip"`                    //  创建账号时的id
	LastLoginIp   string `protobuf:"bytes,11,opt,name=LastLoginIp,proto3" json:"lastloginip" redis:"lastloginip" bson:"lastloginip"`        //  最后一次登录时的ip
}

若@go_tags未指定,会默认生成json,bson,redis的tag,,key统一小写字段名

不推荐使用第三方插件,自己根据需求重写protoc-gen-go重新编译更方便

转换代码:
// 自定义tag转map
func DiyTag2Map(desc string) (string, map[string]string) {
	re := regexp.MustCompile(`@go_tags\((.*?)\)`)
	_findRes := re.FindAllStringSubmatch(desc, 1)
	if _findRes == nil {
		return "", nil
	}
	_diyTags := _findRes[0][1]
	_tagList := strings.Split(_diyTags, " ")
	mapData := make(map[string]string)
	for _, tag := range _tagList {
		_kv := strings.Split(tag, ":")
		_key, _val := strings.Replace(_kv[0], "`", "", -1), strings.Replace(_kv[1], "`", "", -1)
		_runeList := []rune(_val)
		mapData[_key] = string(_runeList[1 : len(_runeList)-1])
	}

	// 把diy的去掉
	desc = re.ReplaceAllString(desc, "")

	return desc, mapData
}
修改源码中部分代码:google.golang.org\protobuf@v1.28.0\cmd\protoc-gen-go\internal_gengo的genMessageField方法,427行开始
func genMessageField(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field, sf *structFields) {
	...
	...
	...
	tags := structTags{
		{"protobuf", fieldProtobufTagValue(field)},
		//{"json", fieldJSONTagValue(field)},  // 屏蔽掉
	}

	// 已声明的tag
	_useTags := make(map[string]bool)
	// 自定义tag
	desc, tagName2Val := DiyTag2Map(string(field.Comments.Trailing))
	if desc != "" {
		field.Comments.Trailing = protogen.Comments(desc)
		for tagName, val := range tagName2Val{
			tags = append(tags, []string{tagName, val})
			_useTags[tagName] = true
		}
	}

	// 默认需要生成json、redis、bson的tag
	_defaultTags := []string{"json", "redis", "bson"}
	// tag的val统一小写字段名,如果是id,需要转换成_id,兼容mongodb
	lowerTag := strings.ToLower(field.GoName)
	if lowerTag == "id" { lowerTag = "_id" }
	for _, tagType := range _defaultTags {
		_, ok := _useTags[tagType]
		// @go_tags声明了不再声明
		if ok {
			continue
		}
		tags = append(tags, []string{tagType, lowerTag})
	}
}
Go
1
https://gitee.com/wnp0818/gogame.git
git@gitee.com:wnp0818/gogame.git
wnp0818
gogame
gogame
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891