Is there something like finally() in Go just opposite to what init()?

huangapple go评论71阅读模式
英文:

Is there something like finally() in Go just opposite to what init()?

问题

在Go语言中,有没有与包内的init()函数相反的功能?

英文:

Is there something in Go which do just opposite to what init() do inside a package?

答案1

得分: 10

这个问题之前已经由Go团队讨论过了,并且他们的结论是不添加对此的支持。引用minux的话:

> 就个人而言,我更喜欢程序退出的方式与程序崩溃的方式完全相同。
我相信无论你多么努力,你的程序在某些意想不到的情况下仍然可能崩溃;例如,内存不足可能导致任何良好行为的Go程序崩溃,而你对此无能为力;所以最好为此进行设计。
如果你遵循这个原则,你就不会觉得需要使用atexit来进行清理(因为当你的程序崩溃时,atexit是不起作用的,所以你根本无法依赖它)。

但是你仍然有一些选择:

处理<kbd>CTRL+C</kbd>

如果你想在程序被<kbd>CTRL+C</kbd>(SIGINT)终止时执行一些操作,你可以这样做,参考:

https://stackoverflow.com/questions/11268943/golang-is-it-possible-to-capture-a-ctrlc-signal-and-run-a-cleanup-function-in

对象终结器

还要注意,你可以为指针值注册一个终结器函数。当垃圾收集器发现一个不可达的块并且有关联的终结器时,它会清除关联并在单独的goroutine中运行f(x)

你可以使用runtime.SetFinalizer()来注册这样的终结器,这可能已经足够了,但要注意:

> 不能保证终结器会在程序退出之前运行,因此它们通常只在长时间运行的程序中用于释放与对象相关的非内存资源。

看看这个例子:

type Person struct {
	Name string
	Age  int
}

func main() {
	go func() {
		p := &amp;Person{&quot;Bob&quot;, 20}
		runtime.SetFinalizer(p, func(p2 *Person) {
			log.Println(&quot;Finalizing&quot;, p2)
		})
		runtime.GC()
	}()

	time.Sleep(time.Second * 1)
	log.Println(&quot;Done&quot;)
}

输出结果(Go Playground):

2009/11/10 23:00:00 Finalizing &amp;{Bob 20}
2009/11/10 23:00:01 Done
英文:

This was discussed before by the Go team, and the conclusion was not to add support for it. Quoting minux:

> Personally, I prefer the style where program exit is handled exactly same as program crash.
I believe no matter how hard you try, your program can still crash under some unforeseen
situations; for example, memory shortage can bring any well-behave Go program to a crash,
and there is nothing you can do about it; so it's better to design for them.
If you follow this, you won't feel the need for atexit to clean up (because when your program
crash, atexit won't work, so you simply can't depend on it).

But you still have some options:

Handling <kbd>CTRL+C</kbd>

If you want to do something when your program is terminated by <kbd>CTRL+C</kbd> (SIGINT), you can do so, see:

https://stackoverflow.com/questions/11268943/golang-is-it-possible-to-capture-a-ctrlc-signal-and-run-a-cleanup-function-in

Object Finalizer

Also note that you can register a finalizer function for a pointer value. When the garbage collector finds an unreachable block with an associated finalizer, it clears the association and runs f(x) in a separate goroutine.

You can register such finalizer with runtime.SetFinalizer() which might be enough for you, but note:

> There is no guarantee that finalizers will run before a program exits, so typically they are useful only for releasing non-memory resources associated with an object during a long-running program.

See this example:

type Person struct {
	Name string
	Age  int
}

func main() {
	go func() {
		p := &amp;Person{&quot;Bob&quot;, 20}
		runtime.SetFinalizer(p, func(p2 *Person) {
			log.Println(&quot;Finalizing&quot;, p2)
		})
		runtime.GC()
	}()

	time.Sleep(time.Second * 1)
	log.Println(&quot;Done&quot;)
}

Output (Go Playground):

2009/11/10 23:00:00 Finalizing &amp;{Bob 20}
2009/11/10 23:00:01 Done

huangapple
  • 本文由 发表于 2015年6月4日 17:44:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/30640439.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定