亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

grpc-go 模型中的空值問題

grpc-go 模型中的空值問題

Go
絕地無雙 2023-06-12 17:25:46
我有兩臺服務器用戶服務器:處理所有用戶增刪改查操作產品服務器:處理產品 CRUD 操作并通過 gRPC 調用從用戶服務器獲取用戶信息type User struct {    ID string `json:"id"`    FirstName      string     `json:"firstName"`    MiddleName     *string    `json:"middleName,omitempty"`    LastName       string     `json:"lastName"`    Email          string     `json:"email"`    Disabled       bool       `json:"disabled"`    LastSignedInAt *time.Time `json:"lastSignedInAt,omitempty"`    Bio            *string    `json:"bio,omitempty"`    BirthDate      *time.Time `json:"birthDate,omitempty"`}這里有些字段是可選的,因為我使用的是 cockroachDB(擴展的 postgreSQL),所以我將它們保存為指針,以便掃描可變形式的查詢結果很容易。這是我的原型文件: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;}現在從上面的原型文件生成的模型是這樣的:“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"`}現在的問題是,因為我正在為可選字段使用指針,它會在沒有值的情況下存儲空值,但在對面的站點上,gRPC 不會理解空值并拋出錯誤。我試過google.protobuf.StringValue像這樣將值作為 grpc 類型google.protobuf.StringValue lastSignedInAt = 8;這可行,但問題是我必須為處理程序中的每個字段編寫條件:if lastSignedInAt != nil {    user.LastSignedInAt = &wrappers.StringValue{Value:*lastSignedInAt}}解決這個問題的最佳方法是什么?我應該更改數據庫模型還是 gRPC 模型中的任何更改?
查看完整描述

3 回答

?
婷婷同學_

TA貢獻1844條經驗 獲得超8個贊

如果協議緩沖區消息的字段可以為 nil,則由您檢查它們。對此你無能為力,除非有一個實用程序包可以做到這一點。

如果您希望默認值高于和超出協議緩沖區生成的默認值,則必須完全按照您的記錄進行操作并檢查是否為 nil。

我確實有一些問題:

  • 為什么對第一個用戶結構中的“可選”字段使用指針?如果您使用普通的舊字符串,它們將在構造時填充空字符串,并且如果該字段丟失,則不會被 json unmarshal 調用觸及。時間字段也一樣。在這種情況下,字符串的默認值(空字符串)應該是無效的中間名,時間的默認值 (0001-01-01 00:00:00 +0000 UTC) 是無效的時間戳(可能?)。擺脫指針允許您使用默認值。

  • 對于原型結構中的時間戳,您仍然可以使用字符串并檢查空字符串?;蛘吣梢允褂?google.protobuf.Timestamp 并使用 ptypes 來處理與非原型結構之間的轉換。


查看完整回答
反對 回復 2023-06-12
?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

grpc 不推薦使用點域,如果你堅持使用指針


一種方法是使用反射來轉換它


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)


查看完整回答
反對 回復 2023-06-12
?
LEATH

TA貢獻1936條經驗 獲得超7個贊

你不能設置空值而不是你可以使用


oneof Examples {

    Example1 example1 = 1;

    Example2 example2 = 2;

}

當你使用 oneof 時,你必須只設置一個值,你可以設置 example1 或 example2 你不能同時使用兩者。與設置 nil 值相比,這將解決您的問題。


方法二:


默認情況下,gRPC 的所有變量都具有初始值 ex: string: ""


您還可以做的一件事是不要設置 nil 值檢查條件,如果您的值為 nil,則什么都不設置。


查看完整回答
反對 回復 2023-06-12
  • 3 回答
  • 0 關注
  • 349 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號