チュートリアルは一通りやったけど実戦はあまり。。
個別処理を調べつつ実装
golangでのCUIコマンドのベースとして参照
Golangで実装するCUIコマンド - Qiita
http://qiita.com/curious-eyes/items/5c109043d0a0c01bb54a
Golang の defer 文と panic/recover 機構について - CUBE SUGAR CONTAINER
http://blog.amedama.jp/entry/2015/10/11/123535
deferって終了処理があるのね。クラス的。
panic() したときにも呼び出されるらしい。
panic/recover の機構が他言語での例外機構のように振る舞うのであれば、error との使い分けをどうすれば良いのだろうか。
...
外部に公開する API はエラーを伝える手段として panic() を使ってはいけない
多値の返り値 w/ error インターフェースを使うこと
panic() はパッケージをまたいで伝搬させることがないようにする
panic/recover 機構はスタックが深くなるような呼び出しをする際に有用
使用することで可読性を向上させることができる
つまり、外部にエラーを伝える手段としては error インターフェースを使うのが正式なやり方で、panic/recover はあくまで内部的に用いるべきもの、ということらしい。
ポインタ参照、、引数を受け取った時にflagパッケージで引数のポインタに。。
みたいなことを踏まえて記述かな。。よくわかってない。
ここではflagパッケージで引数をスクリプト側で設定(flag.Parse)してるのかな。。
failure = flag.Bool("failure", false, "失敗させます")
if *failer{...}
exec.Commandで外部コマンドを実行
Golangで外部コマンドを実行する方法まとめ - Qiita
http://qiita.com/tanksuzuki/items/9205ff70c57c4c03b5e5
引数の扱いとかパイプとかやりたいことはひとまず大体できるのかな。
スライスのdiffをとる
go - How to find the difference between two slices of strings in Golang? - Stack Overflow
http://stackoverflow.com/questions/19374219/how-to-find-the-difference-between-two-slices-of-strings-in-golang
若干変更バージョン
func difference(slice1 []string, slice2 []string, bothFlag int) []string {
var diff []string
// Loop two times, first to find slice1 strings not in slice2,
// second loop to find slice2 strings not in slice1
max := 1
if bothFlag == 1 {
max = 2
}
for i := 0; i < max; i++ {
for _, s1 := range slice1 {
found := false
for _, s2 := range slice2 {
if s1 == s2 {
found = true
break
}
}
// String not found. We add it to return slice
if !found {
diff = append(diff, s1)
}
}
// Swap the slices, only if it was the first loop
if i == 0 {
slice1, slice2 = slice2, slice1
}
}
return diff
}
スライスをループで上書き
arrays - Change values while iterating in golang - Stack Overflow
http://stackoverflow.com/questions/15945030/change-values-while-iterating-in-golang
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
godoc
ドキュメント - golang.jp
http://golang.jp/category/%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88/page/10
若干フォーマットがよくわからん。
シンプルに見えるけどちゃんと書いたほうがいいのかしら。。
逆引きリファレンス的なもの
逆引きGolang (配列)
http://ashitani.jp/golangtips/tips_slice.html#slice_Define
便利そう
できたもの
使い勝手悪いな。。
pecoとかで個別で選択して選べるインターフェイスも。。
たぶん、つくらない。
package main
import (
"flag"
"fmt"
"time"
"os"
"os/exec"
"log"
"strings"
"regexp"
"io"
"github.com/comail/colog"
)
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 difference(slice1 []string, slice2 []string, bothFlag int) []string {
var diff []string
// Loop two times, first to find slice1 strings not in slice2,
// second loop to find slice2 strings not in slice1
max := 1
if bothFlag == 1 {
max = 2
}
for i := 0; i < max; i++ {
for _, s1 := range slice1 {
found := false
for _, s2 := range slice2 {
if s1 == s2 {
found = true
break
}
}
// String not found. We add it to return slice
if !found {
diff = append(diff, s1)
}
}
// Swap the slices, only if it was the first loop
if i == 0 {
slice1, slice2 = slice2, slice1
}
}
return diff
}
/*
お気に入りを開く
*/
func openFavorite(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...")
}
// お気に入りの定義
urlList := []string{
"https://twitter.com/",
}
log.Println("======================== urlList ============================")
log.Println(urlList)
// ブラウザのタブを取得
out, err := exec.Command("chrome-cli", "list", "links").Output()
urlTabs := strings.Split(string(out), "\n")
re := regexp.MustCompile(`^\[[0-9]+?\] `)
for i, _ := range urlTabs {
urlTabs[i] = re.ReplaceAllString(urlTabs[i], "")
//urlTabs[i] = strings.Replace(urlTabs[i], "/[.*]/", "-", 1) // 最後の引数は回数
}
log.Println("======================== urlTabs ============================")
log.Println(urlTabs)
// 差分を取得して開く
diffList := difference(urlList, urlTabs, 0)
log.Println("======================== diff ============================")
log.Println(diffList)
for i, _ := range diffList {
cmd := exec.Command("chrome-cli", "open", diffList[i])
stdin, _ := cmd.StdinPipe()
io.WriteString(stdin, "hoge")
stdin.Close()
out, _ := cmd.Output()
fmt.Printf("結果: %s", out)
}
return nil
}
/*
メイン
*/
func main() {
colog.SetDefaultLevel(colog.LDebug)
colog.SetMinLevel(colog.LTrace)
colog.SetFormatter(&colog.StdFormatter{
Colors: true,
Flag: log.Ldate | log.Ltime | log.Lshortfile,
})
colog.Register()
flag.Parse()
if *version {
fmt.Printf("openFavorite %s\n", VERSION)
os.Exit(0)
}
str := "do something & commit!!"
err := openFavorite(str)
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
str = "and finish!!"
fmt.Fprintf(os.Stdout, "%s\n", str)
}