因此,根据规范,在调用defer函数时会计算defer函数中的值,但是在封闭函数返回之前不会执行这些操作。我得到了这个,并且理解了整个'for i:= 0; i< 4; i ++ defer example打印3210'。
但是,当我尝试使用延迟暂时分配覆盖值(将max m分配给队列长度q)时,请确保在完成后重置值(示例为演示简化):
type tss struct {
q int
m int
}
func (t *tss) test() {
if true {
defer func() {
t.q=t.q //this should evaluate to 't.q = 50' right?
fmt.Println("assigned",t.q,"to t.q")
}()
t.q = t.m
}
fmt.Printf("q=%v, m=%v\n", t.q, t.m)
}
func main() {
ts := tss{50,1}
fmt.Printf("q=%v, m=%v\n", ts.q, ts.m)
ts.test()
fmt.Printf("q=%v, m=%v\n", ts.q, ts.m)
}
我希望收到输出:
q=50, m=1
q=1, m=1
assigned 50 to t.q
q=50, m=1
但实际输出是:
q=50, m=1
q=1, m=1
assigned 1 to t.q
q=1, m=1
所以似乎在错误的时间评估这些值。但是,当我首先将t.q转储到变量中并将该赋值移到延迟函数之外时,将测试函数更改为:
func (t *tss) test() {
if true {
qtmp := t.q
defer func() {
//assigning qtmp here still assigns 1 back to t.q
t.q=qtmp
fmt.Println("assigned",t.q,"to t.q")
}()
t.q = t.m
}
fmt.Printf("q=%v, m=%v\n", t.q, t.m)
}
我得到了上面的预期输出,其中分配了50。
我是否绊倒了一个错误,或者是否有一些关于在延迟函数中分配我缺少的值的事情?
可能需要注意的是,如果我将t.q作为函数参数传递,那也是有效的:
func (t *tss) test() {
if true {
defer func(q int) {
t.q=q
fmt.Println("assigned",t.q,"to t.q")
}(t.q)
t.q = t.m
}
fmt.Printf("q=%v, m=%v\n", t.q, t.m)
}
编辑:这是使用答案中方法的完整版本:
type tss struct {
q int
m int
}
func (t *tss) test() {
if true {
defer func(q int) {
t.q=q //this will correctly evaluate to 't.q = 50'
fmt.Println("assigned",t.q,"to t.q")
}(t.q)
t.q = t.m
}
fmt.Printf("q=%v, m=%v\n", t.q, t.m)
}
func main() {
ts := tss{50,1}
fmt.Printf("q=%v, m=%v\n", ts.q, ts.m)
ts.test()
fmt.Printf("q=%v, m=%v\n", ts.q, ts.m)
}
和正确的输出:
q=50, m=1
q=1, m=1
assigned 50 to t.q
q=50, m=1
答案 0 :(得分:7)
所以我在校对我的帖子时回答了我自己的问题。而不是删除它以掩盖我的尴尬,我会留下它,以防其他人遭受同样的困惑。
延迟函数在调用函数时计算函数的任何ARGUMENTS。它不会立即评估函数体中的任何值。因此,当发生延期行动时,将执行内部分配。
所以:
-Mike
答案 1 :(得分:2)
干净地回答你自己的问题。我认为值得表明对未来读者的初步尝试会有什么修正。
func (t *tss) test() {
if true {
defer func(q int) {
t.q = q //this should evaluate to 't.q = 50' right?
fmt.Println("assigned", t.q, "to t.q")
}(t.q)
t.q = t.m
}
fmt.Printf("q=%v, m=%v\n", t.q, t.m)
}
输出
q=50, m=1
q=1, m=1
assigned 50 to t.q
q=50, m=1