-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
93 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters