从StatusCmd的源码分析返回值
当我们在执行一个函数时,可能会有一个指针形式的返回值,我们不能够直接使用。
而是需要使用此指针的结构体定义的众多方法去将内容返回出来。
函数返回的实质上是*redis.StatusCmd的指针,该类型有以下方法:
Result()
例子1:
//type string connect Redis
func (this *RedisStringAPI) Open(Addr, Password string, DB int) *redis.Client {
//连接
client := redis.NewClient(&redis.Options{
Addr: Addr,
Password: Password, // no password set
DB: DB, // use default DB
})
pong, err := client.Ping().Result()
fmt.Println(pong, err)
return client
}
连接Redis数据库时,我们可以用type Client下的Ping()函数测试一下是否连接成功。
但注意.Result()是必不可少的,否则会出现以下报错:
assignment mismatch: 2 variables but 1 values
这是因为Ping()并非返回了一个string数据类型,我们可以看下Client.Ping()的源码:
func (c cmdable) Ping() *StatusCmd {
cmd := NewStatusCmd("ping")
_ = c(cmd)
return cmd
}
可以发现Ping()函数返回的是StatusCmd指针。
我们再看一下StatusCmd的源码:(此源码位于srcgithub.comgo-redisrediscommand.go)
type StatusCmd struct {
baseCmd
val string
}
var _ Cmder = (*StatusCmd)(nil)
func NewStatusCmd(args ...interface{}) *StatusCmd {
return &StatusCmd{
baseCmd: baseCmd{args: args},
}
}
func (cmd *StatusCmd) Val() string {
return cmd.val
}
func (cmd *StatusCmd) Result() (string, error) {
return cmd.val, cmd.err
}
func (cmd *StatusCmd) String() string {
return cmdString(cmd, cmd.val)
}
func (cmd *StatusCmd) readReply(rd *proto.Reader) error {
cmd.val, cmd.err = rd.ReadString()
return cmd.err
}
可以看到在StatusCmd下有一个Result()方法,可以返回一个string类型。
像是一些查询函数Get()、HGet()等都需要一个Result()函数,原因就是上边探讨的结果。
Err()
例子2:
//type string write
func (this *RedisStringAPI) SetString(client *redis.Client, key, value string, second int) {
//在设置过期时间时,注意单位应该是 *time.Second(或其他单位),并用time.Duration()转换类型
err := client.Set(key, value, time.Duration(second)*time.Second).Err()
if err != nil {
fmt.Println("Set string error:", err)
}
fmt.Println("Set successfully")
}
当我们向Redis写入数据时,可以使用Err()用作验证是否有误,但它不是必须的。
Client.Set()源码:
// Zero expiration means the key has no expiration time.
func (c cmdable) Set(key string, value interface{}, expiration time.Duration) *StatusCmd {
args := make([]interface{}, 3, 4)
args[0] = "set"
args[1] = key
args[2] = value
if expiration > 0 {
if usePrecise(expiration) {
args = append(args, "px", formatMs(expiration))
} else {
args = append(args, "ex", formatSec(expiration))
}
}
cmd := NewStatusCmd(args...)
_ = c(cmd)
return cmd
}
返回的也是StatusCmd,但要注意一下,Err()并不在StatusCmd里,而是在baseCmd,并且StatusCmd和baseCmd是包含关系。StatusCmd嵌套有baseCmd,看下StatusCmd的结构体结构:
type StatusCmd struct {
baseCmd
val string
}
再看下baseCmd的源码:
type baseCmd struct {
args []interface{}
err error
_readTimeout *time.Duration
}
var _ Cmder = (*Cmd)(nil)
func (cmd *baseCmd) Name() string {
if len(cmd.args) == 0 {
return ""
}
// Cmd name must be lower cased.
return internal.ToLower(cmd.stringArg(0))
}
func (cmd *baseCmd) Args() []interface{} {
return cmd.args
}
func (cmd *baseCmd) stringArg(pos int) string {
if pos < 0 || pos >= len(cmd.args) {
return ""
}
s, _ := cmd.args[pos].(string)
return s
}
func (cmd *baseCmd) setErr(e error) {
cmd.err = e
}
func (cmd *baseCmd) Err() error {
return cmd.err
}
func (cmd *baseCmd) readTimeout() *time.Duration {
return cmd._readTimeout
}
func (cmd *baseCmd) setReadTimeout(d time.Duration) {
cmd._readTimeout = &d
}
调用Err()就返回了一个error类型的值。