1 回答

TA貢獻1847條經驗 獲得超11個贊
當運行時檢測到Go代碼無法到達再次引用該變量的點時,該變量將變得不可訪問。
在您發布的示例中, asyscall.Open()
用于打開文件。返回的文件描述符(只是一個int
值)被“包裝”在struct
. 然后一個終結器附加到這個結構值上,關閉文件描述符?,F在,當這個結構值變得不可訪問時,它的終結器可能隨時運行,并且文件描述符的關閉/失效/重用可能會導致Read()
系統調用執行時出現意外行為或錯誤。
p
在Go代碼中這個結構值的最后一次使用是什么時候syscall.Read()
被調用(并且文件描述符p.d
被傳遞給它)。系統調用的實現將在啟動后使用該文件描述符syscall.Read()
,它可能會一直這樣做直到syscall.Read()
返回。但是文件描述符的這種使用是“獨立”于 Go 代碼的。
所以p
在執行系統調用期間不使用結構值,系統調用會阻塞 Go 代碼,直到它返回。這意味著允許 Go 運行時p
在執行期間Read()
(Read()
返回之前)或什至在其實際執行開始之前標記為不可訪問(因為p
僅用于為 call 提供參數Read()
。
因此調用runtime.KeepAlive()
: 因為這個調用在之后并且syscall.Read()
它引用了變量p
,所以 Go 運行時不允許在返回p
之前標記 unreachable Read()
,因為這是在Read()
調用之后。
請注意,您可以使用其他構造來“保持p
活力”,例如_ = p
或返回它。runtime.KeepAlive()
在后臺沒有做任何神奇的事情,它的實現是:
func KeepAlive(interface{}) {}
runtime.KeepAlive()
確實提供了更好的選擇,因為:
它清楚地記錄了我們想要保持
p
活動狀態(以防止運行Finalizers)。使用其他結構,例如
_ = p
可能會被未來的編譯器“優化”出來,但不會被runtime.KeepAlive()
調用。
- 1 回答
- 0 關注
- 188 瀏覽
添加回答
舉報