Is there an idiomatic Go way for abstracting resource allocation/deallocation? My initial guess is to abstract the allocation/deallocation in a higher-order function:
func withResource(f func(Resource)error) error {
// allocate resource
// defer free resource
return f(resource)
}
However, this line of thinking is borrowed directly from the functional paradigm and doesn't seem to align well with Go's largely imperative nature.
As a concrete example, running a daemon for the duration of a block of code is a recurring theme in my current project, so I've created a withDaemon
function to abstract the commonality:
func withDaemon(
cmd *exec.Cmd,
f func(io.ReadCloser, io.ReadCloser, io.WriteCloser) error,
) error {
stdout, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("couldn't get stdout: %v", err)
}
stderr, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("couldn't get stderr: %v", err)
}
stdin, err := cmd.StdinPipe()
if err != nil {
return fmt.Errorf("couldn't get stdin: %v", err)
}
if err := cmd.Start(); err != nil {
return fmt.Errorf("failed to start: %v", err)
}
defer func() {
cmd.Process.Kill()
cmd.Wait()
}
return f(stdout, stderr, stdin)
}