GolangとDBを接続して株価データをチャート表示する

[酒井潤さんのUdemy講座](https://www.udemy.com/go-fintech/)を受講していて、
自分でもGolangとDBを接続して、株価データをチャート表示したくなったので、方法をまとめてみました。

講座ではsqlite3を使用されていましたが、僕はSQLServerを使用しています。基本的にGolangでは一般的なDB(msSqlとか)の接続方法は大体同じだと思います。

※ソース内のコードはエラーハンドリングとかimportとかは省略していますので、悪しからず。

##実装例(4565:そーせいのチャート)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466621/7ed50512-68af-b479-d514-10a9ecd408b8.png)


##テーブル構造
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466621/5fa99d22-270a-941e-73d4-7b66f8454455.png)

##main.go
```main.go
func main() {
	controllers.StartWebServer()
}
```

##webserver.go(contorllers>webserver.go)

```webserver.go
var templates = template.Must(template.ParseFiles("app/views/data.html"))

func dataHandler(w http.ResponseWriter, r *http.Request) {
	//4565:そーせいのデータを表示
	df, _ := models.GetData("4565")
	err := templates.ExecuteTemplate(w, "data.html", df)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func StartWebServer() error {
	http.HandleFunc("/data/", dataHandler)
	return http.ListenAndServe(":8080", nil)
}
```
>####template.Must(template.ParseFiles("app/views/data.html"))
template.Mustはtemplate.ParseFiles(~)で返されたtemplateのポインタ値をエラーをラッピングして、
templateだけを返してくれます。

>####df, _ := models.GetData("4565")
GetDataに株価コードを渡すようにしました。

##stockdata.go(models>stockdata.go)
```stockdata.go
type StockData struct {
	StockCode string  `json:"stockcode"`
	Prices    []Price `json:"price"`
}

type Price struct {
	Time   time.Time `json:"time"`
	Open   float64   `json:"open"`
	Close  float64   `json:"close"`
	High   float64   `json:"high"`
	Low    float64   `json:"low"`
	Volume int32     `json:"volume"`
}

func GetData(stockcode string) (df *StockData, err error) {
	db, err := sql.Open("sqlserver", "server=.;user id=sa;password=password;database=Stock")
	defer db.Close()

	cmd := fmt.Sprintf(`SELECT ～`)
	rows, err := db.Query(cmd)

	df = &StockData{}
	for rows.Next() {
		var price Price
		rows.Scan(&price.Time, &price.Open, &price.Close, &price.High, &price.Low, &price.Volume)
		df.Prices = append(df.Prices, price)
	}
}
```

>####db, err := sql.Open("sqlserver", "server=.;user id=sa;password=password;database=Stock")
sql.Openの第一引数に"sqlserver"、第二引数に接続文字列をセットします。


##data.html

```data.html
 <!DOCTYPE html>
 <html>
 <head>
     <title>Page Title</title>
     <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
     <script type="text/javascript">
        google.charts.load('current', {'packages':['corechart']});
        google.charts.setOnLoadCallback(drawChart);

        function drawChart() {
            var data = google.visualization.arrayToDataTable([
                {{ range .Prices }}
                ['{{.Time}}'.substring(0, 10),{{ .Low }},{{ .Open }},{{ .Close }},{{ .High }}],
                {{end}}
            ], true);

            //お好みで設定
            var options = {...}

            var chart = new google.visualization.CandlestickChart(document.getElementById('chart_div'));

            chart.draw(data, options);
        }
    </script>
    
 </head>
 <body>
 {{ .StockCode }}
 <div id="chart_div" style="width: 900px; height: 500px;"></div>
 </body>
 </html>
```
[options]に設定する内容は[こちら](https://developers.google.com/chart/interactive/docs/gallery/candlestickchart?hl=ja)
>####{{ range .Prices }}
Prices([]Price)をループさせます。

>####['{{.Time}}'.substring(0, 10),{{ .Low }},{{ .Open }},{{ .Close }},{{ .High }}],
ループ中の現在のPrice構造体から日付、安値、始値、終値、高値を順にセットします。
※{{.Time}}から日付(yyyy/MM/dd)だけを抽出する良い方法が浮かばなかったので、substringで対応しました。(良い方法をご存知の方は教えていただけると幸いです)

>####{{end}}
ループを終わります。

これで株価データのチャート表示ができるようになりました。今後はフロントエンド、バックエンド部分の機能拡張を進めていきます。