This package aims to provide a simple and performance oriented mechanism to manage the graceful and reliable shutdown of an application, or parts of it.
It can also be a handy alternative to the context package, though it does not solve the problem that common go libraries only accept context as a valid cancellation method. Therefore, you are only able to cancel "in-between" slow operations.
Check out the sample program for a good overview of this package's functionality.
Let us assume you want a server that should close its connection once it gets closed. We close the connection in the onClose()
method of the server's closer and demonstrate that it does not matter how often you call Close()
, the connection is closed exactly once.
type Server struct {
closer.Closer // Embedded
conn net.Conn
}
func New() *Server {
// ...
s := &Server {
conn: conn,
}
s.Closer = closer.New(s.onClose)
return s
}
func (s *server) onClose() error {
return s.conn.Close()
}
func main() {
s := New()
// ...
// The s.onClose function will be called only once.
s.Close()
s.Close()
}
Now we want an application that (among other things) connects as a client to a remote server. In case the connection is interrupted, the app should continue to run and not fail. But if the app itself closes, of course we want to take down the client connection as well.
type App struct {
closer.Closer
}
func NewApp() *App {
return &App{
Closer: closer.New()
}
}
type Client struct {
closer.Closer
conn net.Conn
}
func NewClient(cl closer.Closer) *Client {
c := &Client{
Closer: cl,
}
c.OnClose(func() error {
return c.conn.Close()
})
return c
}
func main() {
a := NewApp()
// Close c, when a closes, but do not close a, when c closes.
c := NewClient(a.CloserOneWay())
c.Close()
// a still alive.
}
Of course, there is the opposite to the OneWay closer that closes its parent as well. If we take the example from before, we can simply exchange the closer that is passed to the client.
//...
func main() {
a := NewApp()
// Close c, when a closes, and close a, when c closes.
c := NewClient(a.CloserTwoWay())
c.Close()
// a has been closed.
}
Check out godoc for the documentation.
go get github.com/desertbit/closer
We love contributions, so feel free to do so! Coding and contribution guide lines will come in the future. Simply file a new issue, if you encounter problems with this package or have feature requests.