go-redis
庫對於 HSet
方法支援的資料型別為 interface{}
, 檢視下支援哪些型別的
Version
github.com/go-redis/redis/v8 v8.11.5
https://pkg.go.dev/github.com/go-redis/redis/v8@v8.11.5#Client.HSet
Code
type Son struct {
A int
B string
}
type Person struct {
Name string
Age int
Son []Son
}
func TestSerialize(t *testing.T) {
redis := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
data := Person{
Name: "zhangsan",
Age: 18,
Son: []Son{
{
A: 1,
B: "a",
},
{
A: 2,
B: "b",
},
},
}
redis.HSet(context.Background(), "person", "name", data)
}
Debug
可以透過跳轉看到函式內部實現如下
appendArgs
函式將 args
追加到 values
引數的前面後生成一個 IntCmd
物件,傳遞給 c
進行處理(c的定義可以在 NewClient
函式中看到其為 Client
物件)
透過除錯追蹤可以確認 c
為 Client
物件,c
的 Process
方法會將 IntCmd
物件傳遞給 Process
方法進行處理
繼續檢視 process
方法的實現,可以看到跳到了這裡
由於沒有設定 hook
所以直接進入 c.baseClient.process
方法執行
這部分進行重複嘗試,進入 c._process
方法檢視程式碼
忽略頭部的睡眠程式碼,直接下面
c.withConn
傳遞了一個匿名函式,在方法中獲取到一個 conn
物件,然後呼叫該函式
在 withConn
透過傳遞過來的 fn
函式對資料進行序列化處理
序列化的具體實現可以發現是呼叫 writeCmd
方法,進入該方法一路跳轉可以看到具體的執行程式碼
最終兜底處理
Summary
go-redis
庫對於 HSet
方法支援的資料型別為 interface{}
,在傳遞資料時會呼叫 writeCmd
方法進行序列化處理,最終透過 conn
物件將資料傳遞給 redis
服務端
支援的資料型別基本為基礎資料型別,如果是自定義的結構體需要自己實現序列化和反序列化的方式