diff --git a/database/gredis/gredis_conn.go b/database/gredis/gredis_conn.go index 3d4688c69..3eb525137 100644 --- a/database/gredis/gredis_conn.go +++ b/database/gredis/gredis_conn.go @@ -6,9 +6,44 @@ package gredis -import "github.com/gogf/gf/container/gvar" +import ( + "encoding/json" + "github.com/gogf/gf/container/gvar" + "reflect" +) -// DoVar returns value from Do as gvar.Var. +// Do sends a command to the server and returns the received reply. +// It uses json.Marshal for struct/slice/map type values before committing them to redis. +func (c *Conn) Do(commandName string, args ...interface{}) (reply interface{}, err error) { + var ( + reflectValue reflect.Value + reflectKind reflect.Kind + ) + for k, v := range args { + reflectValue = reflect.ValueOf(v) + reflectKind = reflectValue.Kind() + if reflectKind == reflect.Ptr { + reflectValue = reflectValue.Elem() + reflectKind = reflectValue.Kind() + } + switch reflectKind { + case + reflect.Struct, + reflect.Map, + reflect.Slice, + reflect.Array: + // Ignore slice type of: []byte. + if _, ok := v.([]byte); !ok { + if args[k], err = json.Marshal(v); err != nil { + return nil, err + } + } + } + } + return c.Conn.Do(commandName, args...) +} + +// DoVar retrieves and returns the result from command as gvar.Var. func (c *Conn) DoVar(command string, args ...interface{}) (*gvar.Var, error) { v, err := c.Do(command, args...) return gvar.New(v), err diff --git a/database/gredis/gredis_unit_test.go b/database/gredis/gredis_unit_test.go index 4476f0736..09bab562e 100644 --- a/database/gredis/gredis_unit_test.go +++ b/database/gredis/gredis_unit_test.go @@ -281,3 +281,39 @@ func Test_HGetAll(t *testing.T) { }) }) } + +func Test_Auto_Marshal(t *testing.T) { + var ( + err error + redis = gredis.New(config) + key = guid.S() + ) + defer redis.Do("DEL", key) + + type User struct { + Id int + Name string + } + + gtest.C(t, func(t *gtest.T) { + user := &User{ + Id: 10000, + Name: "john", + } + + _, err = redis.Do("SET", key, user) + t.Assert(err, nil) + + r, err := redis.DoVar("GET", key) + t.Assert(err, nil) + t.Assert(r.Map(), g.MapStrAny{ + "Id": user.Id, + "Name": user.Name, + }) + + var user2 *User + t.Assert(r.Struct(&user2), nil) + t.Assert(user2.Id, user.Id) + t.Assert(user2.Name, user.Name) + }) +} diff --git a/go.mod b/go.mod index ecc4e4acc..1c4f42626 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf github.com/mattn/go-runewidth v0.0.9 // indirect github.com/olekukonko/tablewriter v0.0.1 + golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 // indirect golang.org/x/text v0.3.2 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c )