解析 .proto 文件

发布于:2024-12-18 ⋅ 阅读:(55) ⋅ 点赞:(0)

我这里仅仅是介绍了proto这个库解析.proto文件后的参数
我也有个小demo对解析的数据进行使用,具体代码可以看这know-bay
下面解析不是很全面,但是对于现在我的来说是够用的,关于更加详细和全的,看以后是否有机会补充了


假设 .proto 内容如下

syntax = "proto3";

// 测试注释001-01
package gateway.hub.v1;

// 测试注释002-01
option lua_package = "lua/v1";

// 测试注释003-01
service MyService01 {
  // 测试注释004-01
  rpc TestFunc01(TestFunc01Request) returns (TestFunc01Response) {} // 测试注释004-02
  // 测试注释005-01
  // 测试注释005-02
  rpc TestFunc02(TestFunc02Request) returns (TestFunc02Response) {}
}

// 测试注释006-01
message TestFunc01Request {
  string msg = 1;
}

// 测试注释007-01
message TestFunc01Response {
  string msg = 1;
}

message TestFunc02Request {
  string msg = 1;
}

message TestFunc02Response {
  string msg = 1;
}

// ======================================================================================

// 测试注释008-01
service MyService02 {
  // 测试注释009-01
  rpc TestFunc03(TestFunc03Request) returns (TestFunc03Response) {}
}

// 测试注释010-01
message TestFunc03Request {
  string msg2 = 1;
  string msg3 = 2;
  string msg6 = 3;
}

// 测试注释011-01
message TestFunc03Response {
  // 测试注释011-02
  int32 msg10 = 1; // 测试注释011-03
  string msg15 = 2; // 测试注释011-04
}

Option、Package

代码

// 以Option为粒度,处理每个Option定义
func handleOption(o *proto.Option) {
	if o.Name != "lua_package" {
		return
	}

	if !o.Constant.IsString {
		return
	}

	if o.Constant.Source == "" {
		return
	}

	// 拿到.proto文件指定的Option
	fmt.Println(o.Constant.Source)
}

// 以Package为粒度,处理每个Package定义
func handlePackage(p *proto.Package) {
	fmt.Println("proto 的包名:", p.Name)
}

结果

在这里插入图片描述


Service

代码

// 以Service为粒度,处理每个Service定义
func handleService(s *proto.Service) {

	// 查看接口的实际类型和值
	// fmt.Printf("实际类型和值: %T, %v\n", s.Elements, s.Elements)

	// Service 声明的位置【在.proto中的行列位置】
	fmt.Println("Service 声明的位置【在.proto中的行列位置】:", s.Position)
	// Service 的注释
	fmt.Println("Service 的注释:", s.Comment)
	// Service 的名字
	fmt.Println("Service 的名字:", s.Name)
	// Service 的构成部分
	fmt.Println("Service 的构成部分:", s.Elements)
	// Service 所有构成部分
	for i, serviceEach := range s.Elements {
		fmt.Printf("Service 构成部分的第%d个元素:%v\n", i, serviceEach)

		// 检查 each 是否为 *proto.RPC 类型,不是的直接跳过
		mRPC, ok := serviceEach.(*proto.RPC)
		if !ok {
			continue
		}

		// RPC 声明的位置
		fmt.Println("RPC 声明的位置:", mRPC.Position)
		// RPC 的注释
		fmt.Println("RPC 的注释:", mRPC.Comment)
		// RPC 的名字
		fmt.Println("RPC 的名字:", mRPC.Name)
		// RPC 的请求类型
		fmt.Println("RPC 的请求类型:", mRPC.RequestType)
		// RPC 的请求是否为streams
		fmt.Println("RPC 的请求是否为stream:", mRPC.StreamsRequest)
		// RPC 的响应类型
		fmt.Println("RPC 的响应类型:", mRPC.ReturnsType)
		// RPC 的响应是否为streams
		fmt.Println("RPC 的响应是否为stream:", mRPC.StreamsReturns)
		// RPC 的元素
		fmt.Println("RPC 的元素:", mRPC.Elements)
		// 遍历RPC的所有元素
		for j, rpcEach := range mRPC.Elements {
			// 目前看是没有的
			fmt.Printf("RPC 构成部分的第%d个元素:%v\n", j, rpcEach)
		}
		// RPC 的行内注释
		fmt.Println("RPC 的行内注释:", mRPC.InlineComment)
		// RPC 的父节点
		fmt.Println("RPC 的父节点:", mRPC.Parent) // mRPC.Parent.(*proto.Service)

	}
	// Service 的父节点
	fmt.Println("Service 的父节点:", s.Parent) // s.Parent.(*proto.Proto)

}

结果:

在这里插入图片描述


Message

代码

// 以Message为粒度,处理每个Message定义
func handleMessage(m *proto.Message) {

	// 结构体声明的位置
	fmt.Println("结构体声明的位置:", m.Position)
	// 结构体的注释
	fmt.Println("结构体的注释:", m.Comment)
	// 结构体的名字
	fmt.Println("结构体的名字:", m.Name)
	// 结构体是否为扩展
	fmt.Println("结构体是否为扩展:", m.IsExtend)
	// 结构体的元素
	fmt.Println("结构体的元素:", m.Elements)
	// 遍历Message的所有元素
	for i, messageEach := range m.Elements {
		fmt.Printf("Message 构成部分的第%d个元素:%v\n", i, messageEach)

		// 结构体下面的参数信息 messageEach.(*proto.NormalField)
		field, ok := messageEach.(*proto.NormalField)
		if !ok {
			continue
		}

		// 字段声明的位置
		fmt.Println("字段声明的位置:", field.Position)
		// 字段注释
		fmt.Println("字段注释:", field.Comment)
		// 字段名字
		fmt.Println("字段名字:", field.Name)
		// 字段类型
		fmt.Println("字段类型:", field.Type)
		// 字段序列
		fmt.Println("字段序列:", field.Sequence)
		// 字段的Options
		fmt.Println("字段的Options:", field.Options)
		// 字段行内注释
		fmt.Println("字段行内注释:", field.InlineComment)
		// 字段父节点
		fmt.Println("字段父节点:", field.Parent) // field.Parent.(*proto.Message)

		// 字段是否为重复【数组】
		fmt.Println("是否为数组:", field.Repeated)
		// 字段是否为可选字段
		fmt.Println("是否为可选字段:", field.Optional)
		// 字段是否为必须字段
		fmt.Println("是否为必须字段:", field.Required)
	}
	// 结构体的父节点
	fmt.Println("结构体的父节点:", m.Parent) // m.Parent.(*proto.Proto)
}

结果

在这里插入图片描述


一点点笔记,以便以后翻阅。


网站公告

今日签到

点亮在社区的每一天
去签到