Skip to content

Commit

Permalink
add more cmdutil docs
Browse files Browse the repository at this point in the history
  • Loading branch information
svenwltr committed Mar 12, 2018
1 parent 893b44d commit 8526093
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 5 deletions.
93 changes: 93 additions & 0 deletions cmdutil/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Package cmdutil contains helper utilities for setting up a CLI with Go,
// providing basic application behavior and for reducing boilerplate code.
//
// An example application can be found at
// https://github.com/rebuy-de/golang-template.
//
// Graceful Application Exits
//
// In many command line applications it is desired to exit the process
// immediately, if it is clear that the application cannot recover. Important
// note: This is designed for actual applications (ie not libraries), because
// only the application itself should decide when to exit. Libraries should
// alway return errors.
//
// There are three ways to handle fatal errors in Go. With os.Exit() the
// process will terminate immediately, but it will not call any deferrers which
// means that possible cleanup task do not get called. The next way is to call
// panic, which respects the defer statements, but unfortunately it is not
// possible to define an exit code and the user gets confused with a stack
// trace. Finally, the function could just return an error indicating that
// things failed, but this introduces a lot of code, conditionals and appears
// unnecessary, when it is already clear that the application cannot recover.
//
// The package cmdutil provides an alternative, which panics with a known
// struct and catches it right before the application exit. This is an example
// to illustrate the usage:
//
// func main() {
// defer cmdutil.HandleExit()
// run()
// }
//
// func run() {
// defer fmt.Println("important cleanup")
// err := doSomething()
// if err != nil {
// log.Error(err)
// cmdutil.Exit(2)
// }
// }
//
// The defer of HandleExit is the first statement in the main function. It
// ensures a pretty output and that the application exits with the specified
// exit code. The run function does something and makes the application exit
// with an exit code. The specified defer statement is still called. Also the
// application logging facility should be used to communicate the error, so the
// error actually appears on external logging applications like Syslog or
// Graylog.
//
// Minimal Application Boilerplate
//
// Golang is very helpful for creating glue code in the ops area and creating
// micro services. But when you want features like proper logging, a version
// subcommand and a clean structure, there is still a lot of boilerplate code
// needed. NewRootCommand creates a ready-to-use Cobra command to reduce the
// necessary code. This is an example to illustrate the usage:
//
// type App struct {
// Name string
// }
//
// func (app *App) Run(cmd *cobra.Command, args []string) {
// log.Infof("hello %s", app.Name)
// }
//
// func (app *App) Bind(cmd *cobra.Command) {
// cmd.PersistentFlags().StringVarP(
// &app.Name, "name", "n", "world",
// `Your name.`)
// }
//
// func NewRootCommand() *cobra.Command {
// cmd := cmdutil.NewRootCommand(new(App))
// cmd.Short = "an example app for golang which can be used as template"
// return cmd
// }
//
// The App struct contains fields for parameters which are defined in Bind or
// for internal states which might get defined while running the application.
//
// NewRootCommand also attaches NewVersionCommand to the application. It prints
// the compiled version of the application and other build parameters. These
// values need to be set by the build system via ldflags.
//
// BUILD_XDST=$(pwd)/vendor/github.com/rebuy-de/rebuy-go-sdk/cmdutil
// go build -ldflags "\
// -X '${BUILD_XDST}.BuildName=${NAME}' \
// -X '${BUILD_XDST}.BuildPackage=${PACKAGE}' \
// -X '${BUILD_XDST}.BuildVersion=${BUILD_VERSION}' \
// -X '${BUILD_XDST}.BuildDate=${BUILD_DATE}' \
// -X '${BUILD_XDST}.BuildHash=${BUILD_HASH}' \
// -X '${BUILD_XDST}.BuildEnvironment=${BUILD_ENVIRONMENT}' \
package cmdutil
5 changes: 0 additions & 5 deletions cmdutil/exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ func Exit(code int) {
// HandleExit recovers from Exit calls and terminates the current program with
// a proper exit code. It should get deferred at the beginning of the main
// function.
//
// func main() {
// defer cmdutil.HandleExit()
// run() // this function might call Exit anytime
// }
func HandleExit() {
if e := recover(); e != nil {
if exit, ok := e.(exitCode); ok == true {
Expand Down

0 comments on commit 8526093

Please sign in to comment.