protoc-gen-go-xfieldmask

command
v0.0.0-...-a89d410 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 5, 2024 License: Apache-2.0 Imports: 15 Imported by: 0

README

protoc-gen-xfieldMask插件

说明

  • 在protobuf中,google.protobuf.FieldMask 字段用于标识消息体中需要被更新(处理)的字段。
  • protoc-gen-xfieldMask插件基于protobuf自定义扩展字段的方式,以插件->模板的形式在xxx_fm.pb.go文件中生成对应方法,方便客户端和服务端使用fieldMask进行字段选择性处理
  • protoc-gen-xfieldMask可以根据需要选择性mask 请求和响应中的字段。请求和响应中的mask字段不会有冲突
  • protoc-gen-xfieldMask可以深层指定message下的嵌套字段

使用

helloworld.proto(proto/helloworld/v1/helloworld.proto)
syntax = "proto3";

package helloworld.v1;

import "google/protobuf/field_mask.proto";
import "fieldmask/v1/option.proto";

// The greeting service definition.
service GreeterService {
    //  Sends a goodbye greeting
    rpc SayGoodBye (SayGoodByeRequest) returns (SayGoodByeResponse);
}

// The request message containing the greetings
message SayGoodByeRequest{
    // name of the user
    string name = 1;
    // age of the user
    uint64 age = 2;
    // type filter mode
    Type type = 3;
    // update_mask FieldMask
    google.protobuf.FieldMask update_mask = 4[
        // Whether to mask the request field
        (fieldmask.v1.Option).in = true,
        // Whether to mask the request field
        (fieldmask.v1.Option).out = true
    ];
}

// The response message containing the greetings
message SayGoodByeResponse{
    // Data 响应数据
    message Data {
        // name of the user
        uint64 age = 1;
        // age of the user
        string name = 2;
        // other info of the user
        OtherHelloMessage other = 3;
    }
    // error...
    uint32 error = 1;
    // msg...
    string msg = 2;
    // data...
    Data data = 3;
}

// The response OtherHelloMessage containing the greetings
message OtherHelloMessage{
    // id...
    uint32 id = 1;
    // address...
    string address = 2;
}

// Type
enum Type {
    // TYPE_UNSPECIFIED ...
    TYPE_UNSPECIFIED = 0;
    // TYPE_Filter ... filter模式 表示mask的字段被保留
    TYPE_Filter = 1;
    // TYPE_Prune ...  prune模式 表示mask的字段被剔除
    TYPE_Prune = 2;
}
客户端调用(proto/helloworld/v1/fieldmask_test.go)
protoreq := &SayGoodByeRequest{
	Name: "foo",
	Type: Type_TYPE_Filter, // 表示采用过滤模式
}
// MaskInName:表示需要服务端处理name字段;
// MaskOutDataName:表示需要服务端返回data.name字段;
// MaskOutDataOther:表示需要服务端返回data.other下的所有字段
protoreq.MaskInName().MaskOutDataName().MaskOutDataOther()
服务端调用(proto/helloworld/v1/helloworld_impl.go)
func (s *FooServer) SayGoodBye(ctx context.Context, in *SayGoodByeRequest) (out *SayGoodByeResponse, err error) {
    // 初始化过滤/剔除器 
	var fm = new(SayGoodByeRequest_FieldMask)
	if in.Type == Type_TYPE_Filter {
		fm = in.FieldMaskFilter()
	} else {
		fm = in.FieldMaskPrune()
	}
	out = &SayGoodByeResponse{
		Error: 0,
		Msg:   "请求正常",
		Data: &SayGoodByeResponse_Data{
			Age:  1,
			Name: "",
			Other: &OtherHelloMessage{
				Id:      1,
				Address: "bar",
			},
		},
	}
    // 判断是否需要处理name字段
	if fm.MaskedInName() {
		out.Data.Name = in.GetName()
	}
    // 判断是否需要处理age字段
	if fm.MaskedInAge() {
		out.Data.Age = in.GetAge()
	}
    out1, _ := json.Marshal(out)
	fmt.Println("out1:", string(out1)) // out1: {"error":0,"msg":"请求正常","data":{"age":1,"name":"foo","other":{"id":1,"address":"bar"}}}
    // 过滤响应数据
	_ = fm.Mask(out)
	out2, _ := json.Marshal(out)
	fmt.Println("out2:", string(out2)) // out2: {"error":0,"msg":"请求正常","data":{"age":1,"name":"","other":null}}
	return
}

注意

  • 推荐客户端服务端约定使用filter过滤模式
  • message下的嵌套字段如果引入的是外部的消息体,则Mask字段不可再深层指定
  • 目前在框架层面过滤了响应体中的error和msg字段,不管是否masked都会保留在响应体中

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL