In Go, when will a variable become unreachable?

前端 未结 1 526
天命终不由人
天命终不由人 2020-12-18 01:44

Go 1.7 beta 1 was released this morning, here is the release notes draft of Go 1.7. A new function KeepAlive was added to the package runtime. The

相关标签:
1条回答
  • 2020-12-18 02:18

    A variable becomes unreachable when the runtime detects that the Go code cannot reach a point where that variable is referenced again.

    In the example you posted, a syscall.Open() is used to open a file. The returned file descriptor (which is just an int value) is "wrapped" in a struct. Then a finalizer is attached to this struct value that closes the file descriptor. Now when this struct value becomes unreachable, its finalizer may be run at any moment, and the closing / invalidation / re-using of the file descriptor could cause unexpected behavior or errors in the execution of the Read() syscall.

    The last use of this struct value p in Go code is when syscall.Read() is invoked (and the file descriptor p.d is passed to it). The implementation of the syscall will use that file descriptor after the initiation of syscall.Read(), it may do so up until syscall.Read() returns. But this use of the file descriptor is "independent" of the Go code.

    So the struct value p is not used during the execution of the syscall, and the syscall blocks the Go code until it returns. Which means the Go runtime is allowed to mark p as unreachable during the execution of Read() (before Read() returns), or even before its actual execution begins (because p is only used to provide the arguments to call Read().

    Hence the call to runtime.KeepAlive(): since this call is after the syscall.Read() and it references the variable p, the Go runtime is not allowed to mark p unreachable before Read() returns, because this is after the Read() call.

    Note that you could use other constructs to "keep p alive", e.g. _ = p or returning it. runtime.KeepAlive() does nothing magical in the background, its implementation is:

    func KeepAlive(interface{}) {}
    

    runtime.KeepAlive() does provide a much better alternative because:

    • It clearly documents we want to keep p alive (to prevent runs of Finalizers).
    • Using other constructs such as _ = p might get "optimized" out by future compilers, but not runtime.KeepAlive() calls.
    0 讨论(0)
提交回复
热议问题