Reference to another field with in a func in the same struct in golang

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

Reference to another field with in a func in the same struct in golang

问题

我有一个类似这样的结构体:

type Job struct {
    Action  func()
    Cron    string
}

那么对于这个结构体的实例,Action 的实现代码是否可以获取到 Cron 的引用?谢谢。

英文:

I have a struct looks something like this:

type Job struct {
    Action  func()
    Cron    string
}

So for an instance of this struct, is it possible for the code inside the implementation of Action to get a reference to Cron? Thanks.

答案1

得分: 5

使用闭包来创建Action函数:

func MakeAction(job *Job) func() {
    return func() {
        // 使用变量job的函数逻辑
    }
}

你可以像这样使用MakeAction函数:

j := &Job{ nil, "foo" }
j.Action = MakeAction(j)

请注意,当有人复制Job结构体时,这种方式可能会产生意外的结果——由MakeAction()创建的闭包内部的引用仍然指向原始实例(而不是副本)。

英文:

Use a closure to create the Action function:

func MakeAction(job *Job) func() {
    return func() {
        // function that uses the variable job
    }
}

You can use the MakeAction function like this:

j := &Job{ nil, "foo" }
j.Action = MakeAction(j)

Notice that this will behave in possibly unexpected ways when somebody makes a copy of the Job structure—the reference inside the closure created by MakeAction() will still point to the original instance (instead of the copy).

答案2

得分: 3

你似乎必须Job引用传递给Action函数,以便该函数可以访问Cron

例如,参见以下代码:

package main

import "fmt"

type Job struct {
    Action func(*Job)
    Cron   string
}

func main() {
    j := &Job{f, "test"}
    fmt.Println("Hello, playground", j)
    j.Action(j)
}

func f(j *Job) {
    fmt.Println(j.Cron)
}

输出结果为:

Hello, playground &{0x201a0 test}
test

在任何闭包示例中,都无法引用自己的结构体。

OP补充道:

外部框架期望一个这样的函数:func()
我将这个函数包装到了我自己的结构体Job中,并在Job结构体中放入了其他内容。
现在我希望Action能够访问Job中的其他字段,但似乎不可能实现。
稍后我将直接将Action传递给外部框架。

我确认,仅仅通过将func()(来自外部框架)包装在你自己的结构体中,并不意味着f通过闭包可以访问结构体字段。
你需要进行单独的初始化,就像FUZxxl答案所示

否则,那个函数(来自外部框架)怎么会知道Job的存在呢?
这只有在该函数期望一个具有Cron()函数的接口时才能起作用,而不是一个它对其一无所知、具有Cron字段的结构体。
就像这个例子中一样。

英文:

You seem to have to pass a Job reference to the Action function in order for said function to access Cron.

See for instance:

package main

import "fmt"

type Job struct {
	Action func(*Job)
	Cron   string
}

func main() {
	j := &Job{f, "test"}
	fmt.Println("Hello, playground", j)
	j.Action(j)
}

func f(j *Job) {
	fmt.Println(j.Cron)
}

Output:

Hello, playground &{0x201a0 test}
test

None of the closures examples allows you to reference your own struct.


The OP adds:

> The external framework expects a function like this: func().
I'm wrapping this function into my homebrewed struct Job, and I put something else into the Job struct.
Now I hope the Action could access other fields in Job, but it doesn't seem to be possible.
Later I will pass the Action directly into the external framework.

I confirm that, just by wrapping func() (from external framework) in a struct of yours doesn't means f has access to the struct fields through closure.
You need a separate initialization, as FUZxxl's answer shows.

Otherwise, how that function (from an external framework) would even know about Job?
That could only work if that function expect an interface with a Cron() function, not a struct which it knows nothing about, with a Cron field.
As in this example.

huangapple
  • 本文由 发表于 2014年12月25日 18:37:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/27646434.html
匿名

发表评论

匿名网友

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

确定