2013-04-15 15 views
25

Đây là mã của tôi (run):Thông số đóng cửa "trì hoãn" của golang bắt buộc như thế nào?

package main 

import "fmt" 

func main() { 
    var whatever [5]struct{} 

    for i := range whatever { 
     fmt.Println(i) 
    } // part 1 

    for i := range whatever { 
     defer func() { fmt.Println(i) }() 
    } // part 2 

    for i := range whatever { 
     defer func(n int) { fmt.Println(n) }(i) 
    } // part 3 
} 

Output:

0 1 2 3 4 4 3 2 1 0 4 4 4 4 4

Câu hỏi: Sự khác nhau giữa phần 2 & phần 3 là gì? Tại sao phần 2 xuất ra "44444" thay vì ""?

Trả lời

28

Đóng cửa 'phần 2' ghi biến 'i'. Khi mã trong quá trình đóng (sau này) thực hiện, biến 'i' có giá trị mà nó có trong lần lặp cuối cùng của câu lệnh phạm vi, tức là. '4'. Do đó,

4 4 4 4 4 

một phần của đầu ra.

Phần '3' không nắm bắt bất kỳ biến bên ngoài nào trong quá trình đóng. Khi specs nói:

Mỗi lần "hoãn" tuyên bố thực thi, giá trị chức năng và các thông số cuộc gọi được đánh giá như bình thường và lưu một lần nữa nhưng chức năng thực tế không được gọi.

Vì vậy, mỗi cuộc gọi hàm bị trì hoãn có giá trị khác nhau của tham số 'n'. Đó là giá trị của biến 'i' trong thời điểm câu lệnh trì hoãn được thực thi. Do đó

4 3 2 1 0 

một phần của đầu ra vì:

... cuộc gọi hoãn lại được thực hiện theo thứ tự LIFO ngay lập tức trước khi chức năng xung quanh trở lại ...


Các điểm quan trọng cần lưu ý là 'f()' trong 'trì hoãn f()' không phải là được thực hiện khi câu lệnh trì hoãn thực hiện

nhưng

khái niệm 'e' trong 'hoãn f (e)' được đánh giá khi tuyên bố Hoãn thực thi.

Các vấn đề liên quan