Description
Proposal: Make exec
follow guidelines for using Context
objects
Author(s): Casey Barker
Last updated: 2018-07-17
Abstract
This proposal is to add cmd.StartCtx()
and cmd.RunCtx()
methods to the exec
package, eventually deprecating exec.CommandContext()
, and bringing it into compliance with the guidelines for use of Context
objects.
Background
The documentation for the context
package says:
Do not store Contexts inside a struct type; instead, pass a Context explicitly to each function that needs it. The Context should be the first parameter, typically named ctx.
The exec.CommandContext()
function breaks this rule; it stores the ctx
parameter inside the Cmd
object until later referenced by the cmd.Start()
method (which is also called by cmd.Run()
). A caller of cmd.Start()
or cmd.Run()
has no control over which context gets used in the execution.
Issue originally raised here:
https://groups.google.com/forum/#!topic/golang-nuts/uvJIogNTD2c
Looking at the development history for the exec
package's use of context,
I suspect this inconsistency arose accidentally, as the Cmd.ctx
field was used differently early in development.
Proposal
- Add the following two new methods to the
exec
package:
func (c *Cmd) StartCtx(ctx context.Context) error
func (c *Cmd) RunCtx(ctx context.Context) error
These two methods honor the passed-in context, rather than any context that might be attached to the Cmd
.
- Deprecate the following function in the
exec
package:
func CommandContext(ctx context.Context, name string, arg ...string) *Cmd
Once the deprecation is complete, the private ctx
field could be removed from the Cmd
object.
Rationale
The recommendations provided by the context
package are solid; the context object should be passed at the time and place where a long-running operation is started. This makes it clear which calls are long-running, and it allows the source object (in this case, the Cmd
) to be created without needing to know about the ctx
that might eventually be used to control the execution.
Compatibility
Part 1 (adding two new methods) does not break compatibility, although it introduces some possible confusion in that the new methods would ignore the context provided if exec.CommandContext()
were initially used to create the Cmd
object.
Part 2 (deprecating the exec.CommandContext()
function) is a hard break in compatibility.
Implementation
TBD. This is my first proposal and I'm not yet familiar with the Go release process, but I'm willing to provide a patch if this proposal is acceptable.