我有两台服务器
json:"id" FirstName字符串json:"firstName" MiddleName *string json:"middleName,omitempty" LastName string json:"lastName" Email string json:"email"禁用bool json:"disabled" LastSignedInAt *time.Time json:"lastSignedInAt,omitempty" Bio *string json:"bio,omitempty" BirthDate *time.Time json:"birthDate,omitempty" }
这里有一些字段是选项,由于我使用的是cockroachDB(extended ),所以我将它们保留为指针,因此很容易扫描变量表单查询结果。这是我的原始文件:
message User {
int64 id = 1;
string firstName = 2;
string lastName = 3;
string email = 5;
bool disabled = 6;
string lastSignedInAt = 8;
string bio = 9;
string birthdate = 10;
string profession = 14;
}现在从上面的proto文件生成的模型如下所示:“
type User struct {
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
FirstName string `protobuf:"bytes,2,opt,name=firstName,proto3" json:"firstName,omitempty"`
LastName string `protobuf:"bytes,3,opt,name=lastName,proto3" json:"lastName,omitempty"`
Email string `protobuf:"bytes,4,opt,name=email,json=email,proto3" json:"email,omitempty"`
Disabled bool `protobuf:"varint,6,opt,name=disabled,proto3" json:"disabled,omitempty"`
LastSignedInAt string `protobuf:"bytes,8,opt,name=lastSignedInAt,proto3" json:"lastSignedInAt,omitempty"`
Bio string `protobuf:"bytes,9,opt,name=bio,proto3" json:"bio,omitempty"`
Birthdate string `protobuf:"bytes,10,opt,name=birthdate,proto3" json:"birthdate,omitempty"`
}现在的问题是,由于我正在为可选字段使用指针,它将在没有值的情况下存储空值,但在相反的站点上,gRPC将不理解空值并抛出错误。
我尝试过google.protobuf.StringValue值作为grpc类型,如下所示
google.protobuf.StringValue lastSignedInAt = 8;这是可行的,但问题是我必须为处理程序中的每个字段编写条件:
if lastSignedInAt != nil {
user.LastSignedInAt = &wrappers.StringValue{Value:*lastSignedInAt}
}解决这个问题最好的办法是什么?我应该更改数据库模型还是更改gRPC模型?
发布于 2019-03-20 05:00:50
正如上面的另一个答案所指出的,如果协议缓冲区消息中有可以为零的字段,那么您就需要检查它们。你对此无能为力,除非有一个实用程序包。
如果您想要缺省值超出默认协议缓冲区生成的范围,那么您必须完全按照您注意到的那样做,并检查是否为零。
不过,我确实有一些问题:
发布于 2019-03-13 11:31:25
不能将空值设置为可以使用的
oneof Examples {
Example1 example1 = 1;
Example2 example2 = 2;
}当您使用其中一个时,您必须只设置一个值--您可以设置example1或example2 --您不能同时使用这两个值。与设置零值相比,这将解决您的问题。
办法2:
默认情况下,gRPC使所有变量都具有初始值ex: string:"“
您还可以做的一件事是,不要设置零值,如果值为零,则检查条件,然后不设置任何值。
发布于 2019-03-18 09:33:33
如果坚持使用指针,则不建议使用point字段。
一种方法是使用反射来转换它。
func ToGrpcData(in, out interface{}) error {
inVal := reflect.ValueOf(in)
if inVal.Kind() == reflect.Ptr {
inVal = inVal.Elem()
}
inTyp := inVal.Type()
outVal := reflect.ValueOf(out)
if outVal.Kind() != reflect.Ptr {
return errors.New("out data must be point value")
}
outVal = outVal.Elem()
outTyp := outVal.Type()
strWrapperType := reflect.TypeOf(wrappers.StringValue{})
// range all 'in' fields
for i := 0; i < inVal.NumField(); i++ {
fTyp := inTyp.Field(i)
fVal := inVal.Field(i)
if fTyp.Type.Kind() == reflect.Ptr {
switch fTyp.Type.Elem().Kind() {
case reflect.String: // only implement string in this test
oFTyp, ok := outTyp.FieldByName(fTyp.Name)
if ok == false {
return errors.New("not match field in out value")
}
if oFTyp.Type.Elem() != strWrapperType {
return errors.New("not match field in out value")
}
if fVal.IsNil() == false {
outVal.FieldByName(fTyp.Name).Set(
reflect.ValueOf(&wrappers.StringValue{
Value: fVal.Elem().String(),
}),
)
}
}
} else {
outVal.FieldByName(fTyp.Name).Set(fVal)
}
}
return nil
}用法
type User struct {
Name string
Value *string
}
type ServerUser struct {
Name string
Value *wrappers.StringValue
}
usValue := "123"
u1 := User{
Name: "tom",
Value: &usValue,
}
u2 := ServerUser{}
err := ToGrpcData(&u1, &u2)
// error process ...
fmt.Println(u2)https://stackoverflow.com/questions/55140587
复制相似问题