exec.start中的这部分代码是什么意思?

时间:2014-07-09 15:21:43

标签: go

我阅读了exec.Start的代码,有些内容令我困惑。 (* Cmd)。[/ f]中的.stdin / out / err,(* Cmd).stdXX的含义是什么?

   291      type F func(*Cmd) (*os.File, error)
   292      for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
   293          fd, err := setupFd(c)
   294          if err != nil {
   295              c.closeDescriptors(c.closeAfterStart)
   296              c.closeDescriptors(c.closeAfterWait)
   297              return err
   298          }
   299          c.childFiles = append(c.childFiles, fd)
   300      }

2 个答案:

答案 0 :(得分:5)

很好找,我之前不知道那个成语。我会试着把它分解。 首先我们有exec.Cmd

type exec.Cmd struct { ... }

*Cmd有3种方法,包括stdin stdout stderr

func (c *Cmd) stdin() (f *os.File, err error) {...}
func (c *Cmd) stdout() (f *os.File, err error) {...}
func (c *Cmd) stderr() (f *os.File, err error) {...}

现在我想调用所有这些函数并对每个函数执行相同的操作,但我不想创建另一个方法,因为有太多的共享变量要通过参数传递。

第一个解决方案是将代码复制/粘贴3次。不好。

第二种是循环遍历 Functors 的数组。 Functor类型为func(c*Cmd)(f *os.File, err error),因此我们将其声明为

type F (c *Cmd) (f *os.File, err error)

现在我们可以创建一个仿函数数组。但是如何选择*Cmd方法呢?只需使用

(*Cmd).<name of method>

所以它会(*Cmd).stdin, (*Cmd.stdout), (*Cmd).stderr 我们可以将它们用作数组

[]F{ (*Cmd).stdin, (*Cmd.stdout), (*Cmd).stderr }

我们现在只需要打电话给他们

for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} {
    fd, err := setupFd(c)
    ...
}

希望这有帮助。

答案 1 :(得分:1)

我以前从未遇到的一个非常有趣的习语。该代码将*Cmd方法作为函数,并在c上按顺序调用它们。这是一个更简单的代码示例,展示了它的工作原理:http://play.golang.org/p/XwuYD_9uGs

该代码也可以写成for身体,用三个不同的stdXX调用,但这会重复且容易出错,因此作者决定在一个循环中应用三种方法。