0xf

日記だよ

素振り活動: golang

main.go の記述

fujiwara-san のlambroll のコード眺めて、

func main(){
    os.Exit(_main())
}

func _main() int {
    return 0
}

としてるの見て真似しようとなった。

サブプロセスの起動

設定ファイルからコマンドライン指定を受け取って並列実行する。WaitGroup の存在を忘れていた。

golang で構造体にマーシャリング時のマッピング情報をタグ付けするのいつも概念を忘れていて、「おおそうだった」となってしまう。フィールド名大文字じゃないといけないのは、マーシャル処理するパッケージからアクセスできないからか。それはそうか。

func subexec(title, command string, wg *sync.WaitGroup) {
    defer wg.Done()
    cmd := exec.Command("sh", "-c", command)
    output, err := cmd.CombinedOutput()
    if err != nil {
        log.Fatalf("[%v] failed: %v", title, err)
    }
    fmt.Printf("[%v] output:\n%s\n", title, string(output))
    fmt.Printf("[%v] ret value: %v\n", title, cmd.ProcessState)
}

type Shells struct {
    Shells map[string]string `yaml:"shells"`
}

func main() {
    data, err := os.ReadFile("./sample.yml")
    if err != nil {
        panic(err)
    }

    var s Shells
    if err := yaml.Unmarshal(data, &s); err != nil {
        panic(err)
    }

    var wg sync.WaitGroup
    for key, command := range s.Shells {
        fmt.Printf("%s: %s\n", key, command)
        wg.Add(1)
        go subexec(key, command, &wg)
    }
    wg.Wait()
}

こうして、sample.yml にこんな感じのことを書くと並行実行できる。はい。

shells:
   frontend: cd frontend | npm run build -- --watch
   server: cd backend | go run cmd/apps/main.go

web

ginを少し使ってみる。素朴だがコードを見て戸惑うことは少ない。

ルーティング周りの仕様がわかりづらくコードを読んでもやっぱりわかりづらい。パスの処理をめっちゃストレートに実装していて、いかにも高速でフットプリント軽そうではあるけど、ワイルドカード周りの扱いめちゃわかりづらくないですかこれ。脳内で「こういうルーティングを簡単に設定して〜」って思ったことがうまくいかなくてギギギと何度かなった。

例えば、router.StaticFile("/*.html", "./public/index.html") みたいなのが定義できないとか細かい挙動。いや静的ファイルで可変パラメータ関係ないでしょ、というのは思想そのものはわかるとして、では動的な処理としてマッピングできるかというとできない。/:any.html だといけないもんな。any.html ってパラメータにマッピングされてしまう...。いや今時 *.html みたいなの流行らないというのも理解しているんですが...。うっうっ。

ホットリロードの仕組みがないのもイマドキ感が薄い。そういうのはサーバの外でやれ、というのもわかるんだけど。

コマンドライン引数処理

flag パッケージがシンプルでよかった。

ちょっと癖はある。

func main() {
    var n int
    flag.IntVar(&n, "n", 1234, "help message for flag n")
    flag.Parse() // Parseを呼ばないと初期値(1234)が設定されたまま
    fmt.Printf("n = %v\n", n)
    fmt.Printf("args = %v\n", flag.Args())
}

POSIXライクではない。ロングオプションとかも扱いたい場合はサードパーティのものを使えという感じ。