DockerでGo言語開発環境を構築してツールを作成する

## はじめに
* 社内で利用する簡単なツールを作りたい
* dockerで環境構築すればどの言語でも作れはするが、実行するのは社内環境なので同様の環境を構築しなくてはいけない
* どうせ誰も管理しないし作りっぱなしでいいんじゃないか・・・？
* そもそも自分しか使わないのにそこまで構築に時間をかける必要があるのか・・・？

## 利用技術
* docker
* Go言語

## Go言語について
* Googleが開発した言語
* 実行速度・コンパイルが速い
* 調べればいくらでも出てくるので調べてください

## なんでGo言語なのか
* 楽しくプログラミングしてほしいという理念に基づいて開発されているらしいので
* どうせやるならやったことない言語を触ってみたいとは思うので

## dockerで開発環境構築する必要ある・・・？
* ないです
* 今回のテーマがコンテナだったのでそれに絡めるためにです
* dockerの開発にも使われてるのでという逃げ方でも良かったかもしれないですね・・・

## 環境構築
* DockerFileにgoのイメージを利用するように書いてdocekrを立ち上げればOKです。
* 調べればいくらでも出てくるので問題ないでしょう

## docker-compose.yml
* ひねりもないので説明なし

```docker-compose.yml
version: '3'

services:
  golang:
    image: golang
    build: .
    volumes:
      - ./go:/go
    container_name: go_container
    #ポート待ち受けしてないのでこれないとコンテナ落ちる？
    tty: true
    ports:
        - 8080:8080

```

## DockerFile
* こっちも・・・

```DockerFile
FROM golang:latest

WORKDIR /go
ADD ./go /go
```

##　とりあえずhelloworldしよう
* 構文なんざ調べれば出てくるから省略

``` main.go
package main

import "fmt"

func main() {
  fmt.Printf("Hellooooo World\n")
}
```

## ディレクトリ構成

```
.-
 |-docker
  |-golang
   |-go
    |-main.go
   |-DockerFile
   |-docker-compose.yml
```

## 実行〜〜〜
```commandline
docker-compose up -d
docker exec -it go_container bash
↓
root@e069912c2ba0:/go# go run main.go
```

## 開発環境構築完了
* ローカルのgoフォルダをマウントしているので、コンテナ内のファイルにも変更が適応される
* コーディングはVScodeなどで補完効かせた方が楽なはずなのでこの構成に
* と言っても構文は簡単なので、dockerさえ立ち上がる環境であればどこでも作れるのが良いと思う

## go buildでクロスコンパイル
* Go言語を選んだのはここに惹かれた。
* あとはCLIを作りやすいという部分
* 今の所社内ツールと言ってもログの集計やいつも使うようなSQL文を生成するのが面倒なので全部一括でコマンドでできてしまえばと思っている。
* どの環境でも実行できるならもうこっちで管理してなくてもいいんじゃないか・・・？

```bash
# macOS用
env GOOS=darwin GOARCH=amd64 go build main.go
# windows用64bit
env GOOS=windows GOARCH=amd64 go build main.go
```

* これでビルドした実行ファイルを各利用者に渡せば使える

## 毎回コマンド打つのがめんどくさい
* Makefile作ろう

* go用のMakefile


``` Makefile

PACKAGE = PACKAGENAME

run:
	go run main.go
mac:
	env GOOS=darwin GOARCH=amd64 go build ${PACKAGE}
windows:
	env GOOS=windows GOARCH=amd64 go build ${PACKAGE}

```

* Docker用のMakefile

```Makefile

run: up
	docker exec -it go_container make run
connect: up
	docker exec -it go_container bash
up:
	docker-compose up -d
stop:
	docker-compose stop

```

* これ使えばgolang直下で`make run`するだけでdocker内のgoを実行できる

## golangで最強のCLIを作る（仮）

* 私が考える最強のCLIもgolangなら作りやすい
* urfave/cliというパッケージが良さそう。cli用のフレームワークっぽい

```
go get github.com/urfave/cli
```
* これでパッケージ取得

``` go

//fmt:文字出力用
//log:ログ出力用
//os:
//git~:cli作成用パッケージ

package main

import (
	"fmt"
	"log"
	"os"
  
	"github.com/urfave/cli"
  )
  
func main() {
	app := cli.NewApp()
	app.Name = "MostPowerFullCLI!!!!!!!!"
	app.Usage = "if u use this cli. u will be MostPowerFull"
	app.Version = "0.0.1"
	
	
	app.Action = func(c *cli.Context) error {
		fmt.Println("you got a power!!!!!")
		return nil
	}
	

	err := app.Run(os.Args)
	if err != nil {
		log.Fatal(err)
	}
}
```

*　こんなかんじで導入

##### 微妙な解説

* appの中に様々な情報がある
    * app.NameとかでこのCLIツールの名前とかが付けれる
    * Actionなしで実装して実行するとこの情報が表示される。
    *  
* contextにはアプリの情報やコマンドの各引数が渡される
    * context.Argsで引数。stringのsliceされた形式？
    * `context.Args().Get(0)`で１番目の引数が持ってこれる

* 上記コードを実行すると最強の力が得られる

* 複数のコマンドを定義するには以下？

``` go

app.Commands = []cli.Command{
		{
			Name:	"test",
			Aliases:	[]string{"ｔ"},
			Usage:	"this command disp u passed first args",
			Action:	func(c *cli.Context) error {
				fmt.Println("you set first args equal = ", c.Args().First())
				return nil
			},
		},
	}

```

* こんな感じで配列形式で作成すれば、複数のコマンドを定義できる

* これでやれることを増やす感じ？

* こんな感じで自分が使いたいコマンドを作成していく

* やりたいことに関してはGoogle先生に聞いて実装していく


## 作りたい自分用のツール

* 時間なかったというかやる気が出なかったので構想のみ以下・・・

1. 並行処理を用いたDLサイト用アップロードツール
2. 週次、月次ログの集計
3. ログの解析

## 感想

* 基本的にやりたいことがコマンドを打つのがめんどくさいという感じだったので、これで自分用のものを作成していけば大体解決できそうだと思った。

* インデントや構文が決まっていて、これから逸れるとコンパイルできないので誰が書いても綺麗になりそう(誰もやらないと思いますが・・・)

* 誰かに使ってもらうものを考えていたが、結局自分用になりそう

* ただ、使いたいコマンドに関して、ログとか実際に触るものが必要なので、元となるコマンドは結局考えないといけなそうでめんどくさい

* いっそMakefileでいいんじゃねえか疑惑もある

* 依存性に関してよくわかっていない。gitからパッケージを指定していると`go get`
した時に最新のmasterが持ってこられるので、masterがバグってたら動かなくなる・・・？
    * ローカルに持ってきといてそっちを指定する様にした方が良い？最新の方がいいのか・・・？