我正在使用GRPCproto-buffers在GoLang中编写我的第一个API端点。以下是我为我的测试用例编写的文件。
package my_package
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/structpb"
"github.com/MyTeam/myproject/cmd/eventstream/setup"
v1handler "github.com/MyTeam/myproject/internal/handlers/myproject/v1"
v1interface "github.com/MyTeam/myproject/proto/.gen/go/myteam/myproject/v1"
)
func TestEndpoint(t *testing.T) {
conf := &setup.Config{}
// Initialize our API handlers
myhandler := v1handler.New(&v1handler.Config{})
t.Run("Success", func(t *testing.T) {
res, err := myhandler.Endpoint(context.Background(), &v1interface.EndpointRequest{
Data: &structpb.Struct{},
})
require.Nil(t, err)
// Assert we got what we want.
require.Equal(t, "Ok", res.Text)
})
}
这是如何 EndpointRequest
对象的定义是在 v1.go
以上所包含的文件。
// An v1 interface Endpoint Request object.
message EndpointRequest {
// data can be a complex object.
google.protobuf.Struct data = 1;
}
这似乎是工作。
但现在,我想做一些稍微不同的事情。在我的测试案例中,我没有发送一个空的 data
对象,我想发送一个包含键值对的mapdictionary。A: "B", C: "D"
. 怎么做呢?如果我更换 Data: &structpb.Struct{}
与 Data: &structpb.Struct{A: "B", C: "D"}
我得到了编译器错误。
invalid field name "A" in struct initializer
invalid field name "C" in struct initializer
你初始化的方式是 Data
意味着你在期待以下内容。
type Struct struct {
A string
C string
}
然而, structpb.Struct 是这样定义的。
type Struct struct {
// Unordered map of dynamically typed values.
Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// contains filtered or unexported fields
}
很明显,这里有一点不匹配。你需要初始化 Fields
结构的映射,并使用正确的方式来设置 Value
字段。相当于你所展示的代码是。
Data: &structpb.Struct{
Fields: map[string]*structpb.Value{
"A": &structpb.Value{
Kind: &structpb.Value_StringValue{
StringValue: "B",
},
},
"C": &structpb.Value{
Kind: &structpb.Value_StringValue{
StringValue: "D",
},
},
},
}