英文:
Idiomatic Go for abstracting resource allocation/deallocation
问题
有没有一种Go的惯用方式来抽象资源的分配和释放?我最初的想法是在一个高阶函数中抽象出分配和释放的过程:
func withResource(f func(Resource) error) error {
// 分配资源
// 延迟释放资源
return f(resource)
}
然而,这种思路直接借用了函数式范式,并不太符合Go的主要命令式特性。
作为一个具体的例子,在我的当前项目中,运行一个守护进程以执行一段代码是一个经常出现的主题,所以我创建了一个withDaemon
函数来抽象这种共性:
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("无法获取标准输出:%v", err)
}
stderr, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("无法获取标准错误:%v", err)
}
stdin, err := cmd.StdinPipe()
if err != nil {
return fmt.Errorf("无法获取标准输入:%v", err)
}
if err := cmd.Start(); err != nil {
return fmt.Errorf("启动失败:%v", err)
}
defer func() {
cmd.Process.Kill()
cmd.Wait()
}()
return f(stdout, stderr, stdin)
}
以上是翻译好的内容,请确认是否满意。
英文:
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)
}
答案1
得分: 6
我认为惯用的方式是创建一个守护进程类型,并在调用者中使用defer:
d := NewDaemon(...)
defer d.Stop()
doWhatever()
英文:
I think that the idiomatic way would be to create a Daemon type, and to just use defer in the caller:
d := NewDaemon(...)
defer d.Stop()
doWhatever()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论