はじめに
Go開発にて、main.go
で以下のようにハードコーディングしていたDB接続情報をgodotenv
を使って設定ファイルに書き出すように変更したのでメモしておきます。
// DB 接続
func dbConnect() *gorm.DB {
DBMS := "mysql"
USER := "go_test"
PASS := "password"
PROTOCOL := "tcp(db:3306)"
DBNAME := "go_database"
...
目次
1. godotenv とは?
2. .env ファイルの作成・読み込み
3. 参考文献
godotenv とは?
設定(.env)ファイルへ環境変数を定義したい時に使用するライブラリです。
環境変数の定義および管理の煩雑化を防止できます。
以下でインストールを行います。
コマンド実行は、プロジェクトのルートディレクトリ直下です。
go get github.com/joho/godotenv
.env ファイルの作成・読み込み
.env ファイル作成
ディレクトリ構成は以下です。
/
|- .env
|- main.go
|- templates/
|- index.html
.env ファイルは、プロジェクトのルートディレクトリ直下へ作成します。
ちなみにsample.env
等、ファイル名は自由で構いません。
DB_USER=hogehoge
DB_PASSWORD=password
DB=go_database
DB_HOST=db
DB_PORT=3306
DB_PROTOCOL=tcp
DBMS=mysql
パッケージ・ライブラリ定義
今回の目的には直接関連はないのでサラッとご紹介しておきます。
log
:日付、時間、メッセージの表示が可能
os
:ファイルの読み書きが可能
package main
import (
"fmt"
"log" // 追加
"os" // 追加
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"github.com/joho/godotenv" // 追加
)
.env ファイル読み込み
main.go
へ .env ファイル読み込み用のメソッドを追加します。
func envLoad() {
err := godotenv.Load(".env")
if err != nil {
log.Fatalf("Error loading env target")
}
}
DB接続
func dbConnect() *gorm.DB {
// 環境変数から接続文字列を作成
connect := fmt.Sprintf("%s:%s@%s(%s:%s)/%s", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_PROTOCOL"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB"))
// 環境変数からDBMSの種類を取得・DB接続
db, err := gorm.Open(os.Getenv("DBMS"), connect)
if err != nil {
panic(err.Error())
}
return db
}
まとめ
繰り返しになりますが、.env ファイルへ情報をまとめる事で以下の利点が得られます。
・情報の管理が煩雑化しない
・ハードコーディングがなくなり、機能改修等に伴うプログラムの変更も一箇所で済む
改変後
以下が今回変更を加えた後の内容です。
.env の情報を取得 ⇨ DB接続 ⇨ users テーブルのデータを画面一覧へ描画する処理です。
DB_USER=hogehoge
DB_PASSWORD=password
DB=go_database
DB_HOST=db
DB_PORT=3306
DB_PROTOCOL=tcp
DBMS=mysql
package main
import (
"fmt"
"log"
"os"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"github.com/joho/godotenv"
)
type User struct {
gorm.Model
Name string
Department string
Email string
Phone string
}
func main() {
// 設定ファイルから環境変数の情報を取得
envLoad()
db := dbConnect()
db.AutoMigrate(&User{})
defer db.Close()
router := gin.Default()
router.LoadHTMLGlob("templates/*.html")
// users テーブルデータを取得して、index.html へ描画
router.GET("/", func(ctx *gin.Context) {
db := dbConnect()
var users []User
db.Order("created_at asc").Find(&users)
defer db.Close()
ctx.HTML(200, "index.html", gin.H{
"users": users,
})
})
router.Run()
}
// .env ファイル読み込み
func envLoad() {
err := godotenv.Load(".env")
if err != nil {
log.Fatalf("Error loading env target")
}
}
// DB 接続
func dbConnect() *gorm.DB {
// 環境変数から接続文字列を作成
connect := fmt.Sprintf("%s:%s@%s(%s:%s)/%s", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_PROTOCOL"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB"))
// 環境変数からDBMSの種類を取得
db, err := gorm.Open(os.Getenv("DBMS"), connect)
if err != nil {
panic(err.Error())
}
return db
}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>My App</title>
<style>
label {
width: 200px;
float:left;
margin: 0 50px 25px 0;
}
p {
margin-bottom: 5px;
}
input {
height: 20px;
margin-bottom: 10px;
}
tr {
width: 50%;
}
th,td{
border:1px #333 solid;
}
table{
margin-top: 5px;
width: 100%;
border-collapse: collapse;
}
#tdSample {
margin-left: 5px;
}
button {
width: 75px;
height: 30px;
color: #FFF;
background-color: #3CB371;
border: 0;
border-radius: 3px;
cursor: pointer;
font-weight: bold;
}
</style>
</head>
<body>
<h2>ユーザー一覧</h2>
<form method="post" action="/new" style="margin: 10px 50px 10px 50px;">
<div style="width: 100%;">
<label>
<p>氏名</p>
<input type="text" name="name" size="30" placeholder="入力してください">
</label>
<label>
<p>所属部署</p>
<input type="text" name="department" size="30" placeholder="入力してください">
</label>
<label>
<p>メールアドレス</p>
<input type="text" name="email" size="30" placeholder="入力してください">
</label>
<label>
<p>電話番号</p>
<input type="text" name="phone" size="30" placeholder="入力してください">
</label>
<div style="padding-top: 43px;">
<button type="submit">登録</button>
</div>
</div>
</form>
<table style="width: 90%;margin: 10px 50px 10px 50px;">
<tr>
<th style="width: 50px;"></th>
<th>氏名</th>
<th>所属部署</th>
<th>メールアドレス</th>
<th>電話番号</th>
</tr>
{{ range .users }}
<tr>
<td>
<form method="post" action="/delete/{{.ID}}">
<div align="center">
<button type="submit">削除</button>
</div>
</form>
</td>
<td><div id="tdSample">{{ .Name }}</div></td>
<td><div id="tdSample">{{ .Department }}</div></td>
<td><div id="tdSample">{{ .Email }}</div></td>
<td><div id="tdSample">{{ .Phone }}</div></td>
</tr>
{{ end }}
</table>
</body>
</html>
参考文献
[Go 言語]環境変数を使えるようにする方法( godotenv )
log package - log - Go Packages
Go言語(golang) 構造体の定義と使い方
os package - os - Go Packages
strconv package - strconv - Go Packages