docker、Golangでtomlを読み込む

#概要
dockerコンテナでgolangを動かしtomlを読み込んで標準フォーマットで出力する。


#ファイル構成
今回はdockerを使ってコンテナ上で動かしますので以下のファイル構成で行うこととします。

```
goTest
　　├docker-compose.yml
　　├Dockerfile
　　└src
　　　├main.go
　　　├config
　　　│　　└testConfig.toml
　　　└tomlexec
　　　　　 ├tomlexec.go
　　　　　 └tomlexec_test.go
```

#登場ファイル
主な登場ファイルはdockerファイルを除けば難しい事はなく、以下の4ファイルになります。
・main.go
・testConfig.toml
・tomlexec.go
・tomlexec_test.go

各ファイルの設定を見ていきましょう。

###docker-compose.yml
```docker-compose.yml
version: '3.7'
services:
  #golangの設定
  app:
    build: ./
    container_name: goTest
    tty: true
    volumes:
      - ../:/go/src/charts_server/src
    working_dir: /go/src/charts_server/src/goTest/src
    ports:
      - "8080:8080"
    command: go run main.go
    environment:
          - "GOPATH=/go/src/charts_server"
```
#####解説
細かい説明は省きますが、以下の通りとなります。
volumes：localのディレクトリとdockerコンテナのディレクトリの同期をここで行っています。
working_dir：ここで基準になるディレクトリを設定しています。
ports：アクセスする際のポートナンバーです。
environment：ここではdockerコンテナ内でのGOPATHを指定しています。今回は「/go/src/charts_server」

###Dockerfile
```
FROM golang:latest
RUN mkdir /go/src/charts_server
WORKDIR /go/src/charts_server/src/goTest/src
ADD . /go/src/charts_server
```
ここに関してはdockerの設定を行っていますが、シンプルなものとなっていますので説明は不要かと思います。

###main.go
```main.go
package main

import (
	"goTest/src/tomlexec"
)

func main() {
	tomlexec.Exec()
}
```
#####解説
とてもシンプルです。
1階層下のパッケージ、`tomlexec`をインポートして、tomlexecパッケージの`Exec`関数を呼び出しているだけです。

###testConfig.toml
```testConfig.toml
[TestToml]
No    = 1
Name  = "testName"

```
#####解説
今回はgoの構造体に合わせて上記のような設定をしています。
Noはint、Nameはstringとなっています。
`TestToml`に関してはmapで言うkeyのようなものと思えば良いと思います。
`TestToml`と言うキーの中に、`No`、`Name`と言うmapがあると思えば想像しやすいかもしれません。


###tomlExec.go
```tomlExec.go
package tomlexec

import (
	"fmt"

	"github.com/BurntSushi/toml"
)

// TConfig ...
type TConfig struct {
	TestToml *TomlConfig
}

// TomlConfig ...
type TomlConfig struct {
	No   int
	Name string
}

// Exec ...
func Exec() {
	var cfg TConfig
	_, err := toml.DecodeFile("./config/testConfig.toml", &cfg)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(cfg.TestToml.Name)
}
```
#####解説
`TConfig`、`TomlConfig`はそれぞれ、構造体の定義を行っています。
`toml.DecodeFile`で読み込むtomlファイルと読み込ませる構造体を指定しています。
今回は読み込んだ後に`Name`だけ標準出力するようにしています。

###tomlexec_test.go
```tomlexec_test.go
package tomlexec

import (
	"os"
	"path/filepath"
	"testing"
)

func TestExec(t *testing.T) {
	apath, _ := filepath.Abs("../")
	os.Chdir(apath)
	Exec()
}
```
#####解説
tomlExecパッケージのExec関数を呼んでいるだけの簡単なtestです。
ポイントは`filepath.Abs("../")`と`os.Chdir`。
これをやらないとエラーとなってしまいます。
理由はmain.goの実行場所とこのテストの実行場所が違うと言うことです。
最初に挙げたファイル構成を見て頂けるとわかりますが、main.goよりも1階層深い場所にこのテストがあります。
このまま実行すると`./config/testConfig.toml`がどこにあるのかプログラム上では分からなくなり、エラーとなりますが、`filepath.Abs("../")`で1階層下の絶対パスを取得し、それを引数に`os.Chdir`でワーキングディレクトリを指定することで同じように読むことが可能となります。
※pathが崩れてtestが通らない所を、通すのが目的なのでassertなどは記載していません。

##実行
```
goTest> docker-compose up
Starting goTest ... done
Attaching to goTest
goTest | testName
```
`testName`が表示されているのでしっかり読めていますね。

##テスト
手順は
1.起動しているコンテナを検索
2.コンテナの中に入る
3.テストのあるディレクトリまで移動してテストを実行
となります。

```1.起動しているコンテナを検索
goTest> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
c38c50f20df5        gotest_app          "go run main.go"    24 hours ago        Up 27 minutes       0.0.0.0:8080->8080/tcp   goTest 
```

```2.コンテナの中に入る
goTest> docker exec -ti c38c50f20df5 bash
root@c38c50f20df5:/go/src/charts_server/src/goTest/src# 
```

```3.テストのあるディレクトリまで移動してテストを実行
goTest/src# ls 
charts_server  config  main.exe  main.go  tmp  tomlexec
goTest/src# cd tomlexec/
goTest/src/tomlexec# go test -v
=== RUN   TestExec
testName
--- PASS: TestExec (0.01s)
PASS
ok      goTest/src/tomlexec     0.011s
```

ここまでで終了です。
テストも通りました。

一応上記のコードはgitで公開していますので、見たい方は参考までにどうぞ。

[git](https://github.com/loliclo/goTest/tree/tomlTest "git")