go-redis源码中`_ = c(ctx, cmd)`的含义及无函数体可运行原因问询
关于go-redis中
_ = c(ctx, cmd)运行逻辑的解答 你遇到的疑问本质是Go语言函数类型的特性用法,具体逻辑如下:
type cmdable func(ctx context.Context, cmd Cmder) error是函数类型定义,而非接口或者结构体,它本身不需要有统一的实现体,只要签名和它匹配的函数,都可以被转换为cmdable类型使用。- go-redis封装了单节点
Client、集群ClusterClient、分片Ring等多种客户端,每种客户端都有自己独立的命令发送逻辑,这些逻辑的签名都和cmdable的定义完全匹配。 - 你看到的
Get方法是绑定在cmdable类型上的公共方法,这种设计的目的是复用命令封装代码:不用给每一种客户端都单独写一遍Get、Set这类几百个Redis命令的封装,只要把不同客户端的执行逻辑转成cmdable类型,就能直接用所有绑定的命令方法。 - 当你调用
client.Get(...)时,c就是当前客户端对应的执行函数,c(ctx, cmd)实际上执行的就是对应客户端的命令发送逻辑,错误会被写入cmd实例内部,所以这里直接忽略返回值,等后续调用cmd.Result()之类的方法时再透出错误给调用方。
给你举一个简化的复刻示例,方便理解这种写法的逻辑:
// 定义函数类型,对应你看到的cmdable type ExecFunc func(cmd string) error // 给函数类型绑定公共的Get命令方法,对应你看到的Get方法 func (f ExecFunc) Get(key string) (string, error) { cmd := "get " + key // 这里的f调用的就是实际的执行逻辑 err := f(cmd) // 省略结果解析逻辑 return "", err } // 单节点客户端的执行逻辑 func singleNodeExec(cmd string) error { println("单节点执行命令:", cmd) return nil } // 集群客户端的执行逻辑 func clusterExec(cmd string) error { println("集群执行命令:", cmd) return nil } func main() { // 单节点场景:把单节点执行函数转成ExecFunc就可以用Get方法 singleCli := ExecFunc(singleNodeExec) singleCli.Get("test_key") // 集群场景同理,不需要再单独写Get方法 clusterCli := ExecFunc(clusterExec) clusterCli.Get("test_key") }
这是Go语言中非常常用的代码复用技巧,把可变的底层执行逻辑和固定的上层命令封装解耦,后续新增Redis命令只需要在cmdable的方法列表里加一次,所有类型的客户端都可以直接支持。
内容的提问来源于stack exchange,提问作者t y
相关产品推荐
相关产品推荐

