For example, if p points to a struct, such as os.File, that contains a file descriptor d, and p has a finalizer that closes that file descriptor, and if the last use of p in a function is a call to syscall.Write(p.d, buf, size), then p may be unreachable as soon as the program enters syscall.Write. The finalizer may run at that moment, closing p.d, causing syscall.Write to fail because it is writing to a closed file descriptor (or, worse, to an entirely different file descriptor opened by a different goroutine). To avoid this problem, call KeepAlive(p) after the call to syscall.Write.
SetFinalizer提供了一个机制:当对象即将被垃圾回收时,调用一个回调函数。
这听起来很像是C++的析构函数,但是现实中很少看到有人这样使用。 一个很大的问题是,当对象不可达时,被GC回收的时机是不可控的。可能goroutine退出了都还没回收;有时候对象的作用域还没结束,但是因为后面没有引用,而立即被回收也可能发生
标准库os.File都不敢用这种方式关闭文件,只能老老实实用defer。 因此,SetFinalizer建议只在追踪代码时使用,不建议放逻辑相关的代码