Help us understand the problem. What is going on with this article?

Golangで実装するCUIコマンド

More than 3 years have passed since last update.

最近、RDB(Mysql)を操作するバッチ処理を実装することが多く、お勉強がてらgolangを使い始めました。

やることはいつも

  • パラメーター判断
  • トランザクション制御
  • ログ出力

こんな感じなので、
golangの動作確認を兼ねて、コマンドアプリのひな型になりそうなサンプルを作りました。

package main

import (
  "flag"
  "fmt"
  "time"
  "os"
)

const VERSION = `0.0.1`

type ErrMessage struct {
    What string
}
func (e ErrMessage) Error() string {
    return fmt.Sprintf("%v: %v", time.Now(), e.What)
}

var (
  version = flag.Bool("V", false, "display version information")
  failure = flag.Bool("failure", false, "失敗させます")
)

func DoSomething(str string) (err error) {
    defer func() {
      // panicがおきたらRollback
      if e := recover(); e != nil {
          fmt.Fprintf(os.Stderr, "Rollback!!\n")
          // エラーメッセージフォーマット変換
          x, _ := e.(string)
          err = ErrMessage{x}
      }
    }()

    if *failure {
      // Error発生
      panic("DoSomething error...")
    }

    fmt.Fprintf(os.Stdout, "%s\n", str)
    return nil
}

func main() {
  flag.Parse()
  if *version {
    fmt.Printf("dosomething %s\n", VERSION)
    os.Exit(0)
  }

  str := "do something & commit!!"
  err := DoSomething(str)
  if err != nil {
    fmt.Fprintf(os.Stderr, "%s\n", err)
    os.Exit(1)
  }

  str = "and finish!!"
  fmt.Fprintf(os.Stdout, "%s\n", str)
}

パラメーターの実装は、flagを使えば楽ですね。

トランザクション制御について、
異常時のRollBackを実行するには、deferとrecover()を使えば良さそうです。
どのような動きになるのか、パラメーターで動作を分けて試してみました。

また、
ログ出力時、メッセージフォーマットを自作するサンプルがあったので、採用してみました。
正常時のログはStdoutへ、異常時はStderrへ出力したいですから、そのあたりも実装してます。
fmt.Fprintf() に標準出力(os.Stdout)、標準エラー(os.Stderr)のファイルディスクリプタを渡します。

さて、実行してみましょう。
実行時パラメータ無しで、正常終了します。

$ (コマンド) 2>./stderr.log 1>./stdout.log

などとやれば、stderr.log には、何も出力されず、
stdout.log にログが出力されます。

failureパラメータをつけると、異常時の動作を確認できます。
(実際にはこんなパラメータは要らないですが...)

$ (コマンド) --failure 2>./stderr.log 1>./stdout.log

stderr.log で、deferに指定した処理が実行されたことがわかります。
stdout.logには出力されません。

何か異常があれば、すぐにpanic()を起こしてrollbackしてしまいましょう。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away