go - 如何将 protoc-gen-go gzipped FileDescriptorProto 显示为纯文本?

标签 go protocol-buffers protoc

protoc-gen-go 在生成的 go 文件末尾生成类似以下内容:


var fileDescriptor_13c75530f718feb4 = []byte{
    // 2516 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x59, 0xdf, 0x6f, 0x1c, 0x47,
...
}

我想以纯文本形式阅读它以进行调试。如何做到这一点?

为什么我想要它 - 一个不应该不会在这个生成的文件中产生变化的小变化确实,我正在弄清楚为什么(而且很难调试,因为它只是一个二进制 blob)。

最佳答案

我编写了这样的代码来解析和打印 blob。

关键逻辑其实来自https://github.com/grpc/grpc-go/blob/759de4dd00c25745b6f3d7a9fdfb32beaf1d838e/reflection/serverreflection.go#L202-L226

package main

import (
    "bytes"
    "compress/gzip"
    "encoding/json"
    "fmt"

    "io/ioutil"

    proto "github.com/golang/protobuf/proto"
    dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
    _ [here write path to your generated go source]
    // include the line above if you want to use proto.FileDescriptor,
    // leave if you just copy-paste the bytes below
)

func main() {
    // here write the path that is used in the generated file
    // in init(), as an argument to proto.RegisterFile 
    // (or just copypaste the bytes instead of using proto.FileDescriptor)
    bytes := proto.FileDescriptor(XXX)

    fd, err := decodeFileDesc(bytes)
    if err != nil {
        panic(err)
    }
    b, err := json.MarshalIndent(fd,"","  ")
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))
}

// decompress does gzip decompression.
func decompress(b []byte) ([]byte, error) {
    r, err := gzip.NewReader(bytes.NewReader(b))
    if err != nil {
        return nil, fmt.Errorf("bad gzipped descriptor: %v", err)
    }
    out, err := ioutil.ReadAll(r)
    if err != nil {
        return nil, fmt.Errorf("bad gzipped descriptor: %v", err)
    }
    return out, nil
}

func decodeFileDesc(enc []byte) (*dpb.FileDescriptorProto, error) {
    raw, err := decompress(enc)
    if err != nil {
        return nil, fmt.Errorf("failed to decompress enc: %v", err)
    }

    fd := new(dpb.FileDescriptorProto)
    if err := proto.Unmarshal(raw, fd); err != nil {
        return nil, fmt.Errorf("bad descriptor: %v", err)
    }
    return fd, nil
}

这会以 JSON 形式打印 proto 文件中的数据。

正如 Marc Gravell 在另一个答案的评论中提到的那样,gzip 压缩是不确定的,因此同一个 proto 文件可以在两台不同的计算机上创建不同的 gzip 压缩 FileDescriptorProto。

关于go - 如何将 protoc-gen-go gzipped FileDescriptorProto 显示为纯文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60540511/

相关文章:

Golang 模块问题--package xxx/xxxx is not in GOROOT

unit-testing - 有没有办法动态设置测试超时值

java - Protobuf配置Intellij Idea Plugin Gradle-kotlin-dsl kotlin

json - "google/protobuf/struct.proto"是通过 GRPC 发送动态 JSON 的最佳方式吗?

dart - Mac OS 上的 Protobuf dart 生成找不到 protoc-gen-dart

go - 从客户端向服务器发送大量数据

unit-testing - (*testing.common).Errorf 不支持错误包装指令 %w

c++ - 使用反射在 protobuf 消息中设置 oneof

java - 在 Google 的 Protocol Buffers 中,什么是适合异常的协议(protocol)文件/模型?

python - 从 object_detection.protos 导入 string_int_label_map_pb2 ModuleNotFoundError :