” _ = c(ctx, cmd)” 这句代码的含义是什么?

huangapple go评论80阅读模式
英文:

What does " _ = c(ctx, cmd)" mean?

问题

_ = c(ctx, cmd) 是一个函数调用语句,它的作用是调用函数 c 并传入参数 ctxcmd。这里使用 _ 是为了忽略函数返回的结果,即不关心函数的返回值。在这段代码中,_ = c(ctx, cmd) 的目的可能是为了执行一些副作用,而不需要使用函数的返回值。至于函数 c 的具体实现,你在代码中找不到它的定义是因为 cmdable 是一个函数类型的别名,它可以被赋值为任何具有相同参数和返回值的函数。所以你需要在其他地方找到 cmdable 类型的具体实现来了解函数 c 的实际行为。你可以在 https://github.com/go-redis/redis/blob/master/commands.go#L780 找到 cmdable 类型的定义。希望对你有帮助!

英文:

I'm reading the code that go-redis library, and then I want to know how the _ = c(ctx, cmd) works.

// Get Redis `GET key` command. It returns redis.Nil error when key does not exist.
func (c cmdable) Get(ctx context.Context, key string) *StringCmd {
	cmd := NewStringCmd(ctx, "get", key)
	_ = c(ctx, cmd)
	return cmd
}

I found type alias below but I couldn't find this function's body.

type cmdable func(ctx context.Context, cmd Cmder) error

why and how _ = c(ctx, cmd) works without function body?

https://github.com/go-redis/redis/blob/master/commands.go#L780

Thanks!

答案1

得分: 5

cmdable被定义为type cmdable func(ctx context.Context, cmd Cmder) error。因此,它是一个函数的别名,可以从方法中调用自身。这与任何其他函数变量的工作方式相同:

abc := func(ctx context.Context, cmd Cmder) error {
    fmt.Println("我们可以在这里做任何事情")
    return nil
}

cmd := cmdable(abc)

因此,实际的函数体在此结构体之外提供。例如,它们在几个地方使用,这是Client的定义:

type Client struct {
    *baseClient
    cmdable
    hooks
    ctx context.Context
}

它嵌入了cmdable,因此cmdable上的所有公开方法也将成为Client上的公开方法。在NewClient中创建Client时,将cmdable设置为c.Process

func NewClient(opt *Options) *Client {
    opt.init()

    c := Client{
        baseClient: newBaseClient(opt, newConnPool(opt)),
        ctx:        context.Background(),
    }
    c.cmdable = c.Process

    return &c
}

因此,在Client的情况下,Client.Processc的函数体。但对于Pipeline,设置了Pipeline.Process。他们这样做是因为您希望在提交管道之前排队命令。

因此,这是从抽象结构继承和策略模式的组合。


_ =丢弃了返回值,该返回值是一个error。像这样使用下划线被称为空白标识符。这不是严格必要的,但可能是为了向诸如go vet之类的工具表明这是有意的,作者没有忘记检查错误。

英文:

cmdable is defined as type cmdable func(ctx context.Context, cmd Cmder) error. So because it is an alias of a function it can call itself from a method. This works just like any other function variable:

abc := func(ctx context.Context, cmd Cmder) error {
    fmt.Println("we can do anything here")
    return nil
}

cmd := cmdable(abc)

So the actual function body is provided outside of this struct. They use it in a few places for example, this is the definition of Client:

type Client struct {
	*baseClient
	cmdable
	hooks
	ctx context.Context
}

It embeds cmdable so all exported methods on cmdable will become exported methods on Client as well. During creating of the Client in NewClient the cmdable is set to c.Process:

func NewClient(opt *Options) *Client {
	opt.init()

	c := Client{
		baseClient: newBaseClient(opt, newConnPool(opt)),
		ctx:        context.Background(),
	}
	c.cmdable = c.Process

	return &c
}

So in the case of Client, Client.Process is the body of c. But for Pipeline, Pipeline.Process is set. They do this because you want to queue commands before committing the pipeline.

So this is sort of a combination of inheritance from an abstract struct and a strategy pattern.


The _ = discards the return value which is an error. Using an underscore like this is called a blank identifier. This is not strictly necessary but is likely done to indicate to tools like go vet that this is on purpose and that the author didn't forget to check an error.

huangapple
  • 本文由 发表于 2021年11月26日 03:54:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/70116600.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定