登录
首页 >  Golang >  Go问答

比较两个 Go 中 protobuf 消息定义的读取方式

来源:stackoverflow

时间:2024-02-22 11:45:23 335浏览 收藏

golang学习网今天将给大家带来《比较两个 Go 中 protobuf 消息定义的读取方式》,感兴趣的朋友请继续看下去吧!以下内容将会涉及到等等知识点,如果你是正在学习Golang或者已经是大佬级别了,都非常欢迎也希望大家都能给我建议评论哈~希望能帮助到大家!

问题内容

上下文:我正在尝试解决此问题。

换句话说,有一个用于 json 字符串的 normalizejsonstring() (有关更多上下文,请参阅此内容:

// takes a value containing json string and passes it through
// the json parser to normalize it, returns either a parsing
// error or normalized json string.
func normalizejsonstring(jsonstring interface{}) (string, error) {

允许有以下代码:

return structure.normalizejsonstring(old) == structure.normalizejsonstring(new)

但它不适用于原始文件的字符串(所有原始文件都保证只有一个消息定义)。例如,我可以看到:

syntax = "proto3";
          - package bar.proto;
            
          + package bar.proto;
            option java_outer_classname = "FooProto";
            
            message Foo {
              ...
          -   int64 xyz = 3;
          +   int64  xyz = 3;

某些 go sdk 中是否有 normalizeprotostring 可用?我找到了 messagedifferencer 但它仅使用 c++ 语言。我考虑的另一个选择是用单个空格替换所有新行/一组空格,但这有点hacky。


正确答案


要以语义方式做到这一点,应该真正解析原始定义。天真地剥离和/或替换空格可能会让您有所收获,但可能会遇到问题。

据我所知,最新的官方 go protobuf 包没有任何东西来处理解析 protobuf 定义 - protoc 编译器处理这方面的事务,这是用 c++ 编写的

选项可以执行 protoc 编译器来获取描述符集输出(例如 protoc --descriptor_set_out=...),但是我猜这也会稍微有点偶然考虑到它需要 protoc 可用 - 并且版本差异也可能导致问题。

假设不行,还有一个选择是使用用 go 编写的第三方解析器 - github .com/yoheimuta/go-protoparser 似乎处理得很好。进行比较时的一个小问题是解析器记录有关每种类型的源行+列位置的元信息;然而,通过使用 github.com/google/go-cmp 进行比较并忽略这些相对容易

例如:

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/google/go-cmp/cmp"
    "github.com/google/go-cmp/cmp/cmpopts"
    "github.com/yoheimuta/go-protoparser/v4"
    "github.com/yoheimuta/go-protoparser/v4/parser"
    "github.com/yoheimuta/go-protoparser/v4/parser/meta"
)

func main() {
    if err := run(); err != nil {
        log.fatal(err)
    }
}

func run() error {
    proto1, err := parsefile("example1.proto")
    if err != nil {
        return err
    }

    proto2, err := parsefile("example2.proto")
    if err != nil {
        return err
    }

    equal := cmp.equal(proto1, proto2, cmpopts.ignoretypes(meta.meta{}))

    fmt.printf("equal: %t", equal)

    return nil
}

func parsefile(path string) (*parser.proto, error) {
    f, err := os.open(path)
    if err != nil {
        return nil, err
    }
    defer f.close()

    return protoparser.parse(f)
}

输出:

equal: true

对于您提供的示例。

以上就是《比较两个 Go 中 protobuf 消息定义的读取方式》的详细内容,更多关于的资料请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>