为了账号安全,请及时绑定邮箱和手机立即绑定

golang defer 未按预期进行评估

golang defer 未按预期进行评估

Go
qq_遁去的一_1 2021-09-13 16:22:16
因此,根据规范,在调用 defer 函数时会评估 defer 函数中的值,但在封闭函数返回之前不会执行操作。我明白了,并理解了整个 'for i:=0;i<4;i++ defer example prints 3210' 的事情。但是,当我尝试使用 defer 临时分配覆盖值(将 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=1q=1, m=1assigned 50 to t.qq=50, m=1但实际输出是:q=50, m=1q=1, m=1assigned 1 to t.qq=1, m=1因此,这些值似乎是在错误的时间进行评估的。但是,当我首先将 tq 转储到变量中并将该赋值移到延迟函数之外,并将测试函数更改为如下所示: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。我是否遇到了错误,或者是否有关于在我缺少的延迟函数中分配值的问题?可能值得注意的是,如果我将 tq 作为函数参数传入,它也能正常工作: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)}
查看完整描述

2 回答

?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

所以我在校对我的帖子时回答了我自己的问题。与其删除它以掩饰我的尴尬,不如将其保留,以防其他人遭受同样的困惑。

deferred 函数在调用时计算该函数的任何 ARGUMENTS。它不会立即评估函数体内的任何值。因此,在延迟操作发生时执行内部分配。

所以:

  1. 代码运行

  2. 遇到 defer 语句

  3. golang 存储参数值以备后用

  4. 延迟函数的主体被完全忽略

  5. 其余代码运行到封闭函数的末尾

  6. 使用存储的参数值执行延迟函数

-麦克风


查看完整回答
反对 回复 2021-09-13
?
青春有我

TA贡献1784条经验 获得超8个赞

很好地回答你自己的问题。我认为值得向未来的读者展示对您最初尝试的更正。


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


查看完整回答
反对 回复 2021-09-13
  • 2 回答
  • 0 关注
  • 170 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信