LoginSignup
3
5

この記事ではGoのginフレームワークを用いてデータベースサーバーからデータを取得し,JSON形式で表示することを目標とする.今回はdockerで環境構築をする.DBMSはPostgreSQLを用いる.

goのバージョンは1.22を用いる

Dockerで環境構築

まずプロジェクトディレクトリを作成する.

mkdir yourprojectname
cd yourprojectname

goプロジェクトを始めるために新しいGoモジュールを初期化する

go mod init example.com/yourprojectname

次にginフレームワークをインストールする.

go get -u github.com/gin-gonic/gin

DBサーバー(PostgreSQL)からデータを取ってくるための依存関係を追加する.

go get github.com/lib/pq
go get golang.org/x/net

go get github.com/lib/pq
Go言語でPostgreSQLデータベースに接続するためのドライバ.GoプログラムからPostgreSQLデータベースに接続し,クエリを実行することができる.
go get golang.org/x/net
Goの標準ライブラリを補完するネットワーク関連のパッケージを提供する.以下のようなサブパッケージが含まれている

net 追加のネットワーク関連の機能を提供する.
http2 HTTP/2プロトコルのサポートを提供する.
websocket WebSocketプロトコルのクライアントとサーバーの実装を提供する.
proxy プロキシ関連の機能を提供する.

Dockerコンテナを作成する.

touch Dockerfile

Dockerfileの中身は以下のようにする.

FROM golang:1.22-alpine

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .

RUN go mod tidy

RUN go build -o main .

EXPOSE 8080

CMD ["./main"]

ついでにdocker-compose.ymlも作成する.

touch docker-compose.yml

今回はコンテナは1つだけだし不要では...ある

docker-compose.yml
version: '3'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - PORT=8080

main.go(それぞれのgoファイル実行用)の作成

次にそれぞれのgoファイルを実行する専用のgoファイルmain.goを作成する.

touch main.go
main.go
package main

import (
	//一旦空白で
)

func main() {
    //一旦空白で
}

getdb.go(実際のロジック書くところ)の作成

次に実際にデータを受け取るロジックを書くgoファイルgetdb.goを格納するディレクトリを作成する.

mkdir getdb

各エンドポイントごとにディレクトリを作成すると今後規模が大きくなってきたときに探しやすくなる

getdb.goを作成し,以下のように書く.

touch getdb/getdb.go

ソースコードの細かい説明はコメントアウトしておきました.

getdb/getdb.go
package getdb

import (
	"database/sql"
	"net/http"

	"github.com/gin-gonic/gin"
	_ "github.com/lib/pq"
)

// Run関数は,データベースとの接続を確立し、APIサーバーを起動する
func Run() {
	// sql.Open関数を使用して,指定されたデータベースサーバーへの接続を開く
	db, err := sql.Open("postgres", "取得したいDBサーバーのリンク")

	// エラーが発生した場合は,panic関数でプログラムを終了する
	if err != nil {
		panic(err)
	}
	// defer db.Close()により,関数の最後にデータベース接続を閉じるようにする
	defer db.Close()

	// Ginフレームワークを使用してルーターを作成する
	router := gin.Default()

	// router.GETメソッドを使用して,/getdbエンドポイントを定義する
	router.GET("getdb", func(c *gin.Context) {
		// db.Query関数を使用し,指定されたSQLクエリを実行し,結果を取得する
		rows, err := db.Query("SELECT * FROM \"テーブル名\";")
		// エラーが発生した場合は,ステータスコード500(Internal Server Error)とエラーメッセージをJSONレスポンスで返す
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
		// defer rows.Close()により,関数の最後に結果セットを閉じるようにする
		defer rows.Close()

		// data変数を定義して,取得したデータを格納するためのスライスを初期化する
		var data []map[string]interface{}
		// rows.Columns()関数を使用して,結果セットのカラム名を取得する
		columns, _ := rows.Columns()
		// rows.Next()メソッドを使用して,結果セットの各行をループ処理する
		for rows.Next() {
			// 各行の値を格納するためのvaluesスライスとvaluePtrsスライスを作成する
			values := make([]interface{}, len(columns))
			valuePtrs := make([]interface{}, len(columns))
			for i := range columns {
				valuePtrs[i] = &values[i]
			}

			// rows.Scan関数を使用して,現在の行の値をスキャンし,valuesスライスに格納する
			err := rows.Scan(valuePtrs...)
			// エラーが発生した場合は,ステータスコード500(Internal Server Error)とエラーメッセージをJSONレスポンスで返す
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			// item変数を定義して,カラム名と値のマップを作成する
			item := make(map[string]interface{})
			for i, col := range columns {
				item[col] = values[i]
			}
			// dataスライスにitemを追加する
			data = append(data, item)
		}

		// c.JSON関数を使用して,ステータスコード200(OK)と取得したデータをJSONレスポンスで返す
		c.JSON(http.StatusOK, data)
	})

	// router.Runメソッドを使用して,指定されたポート番号でAPIサーバーを起動する
	// ポート番号は8080
	router.Run(":" + "8080")
}

main.goにロジックが書かれたファイルへの依存関係を追加

ルートのmain.goにgetdb/getdb.goへの依存関係を追加し,Run関数を実行するようにする.

main.go
package main

import (
	"example.com/yourprojectname/getdb"
)

func main() {
	getdb.Run()
}

実行

dockerコンテナを起動する

docker compose up

コンテナが立ち上がったら,以下のリンクにアクセスすればデータが返ってくるはずだ.
http://localhost:8080/getdb

デプロイ

これをherokuにデプロイするにはgo.sumgo.modがプロジェクトに存在する必要がある.go.modはすでに存在すると思うのでgo.sumを初期化して生成する必要がある.go.sumはdockerコンテナ内で実行するようになってはいるが,go.modが適用されているか確認してほしい,できていないのであれば以下のコマンドを実行すること.

go.modファイルは,プロジェクトのモジュール情報と依存関係を定義し,go.sumファイルは,依存関係の正確なバージョンとチェックサムを記録する.

あればスキップしてね

go mod tidy

ここまで作成した全てのファイルをgitリポジトリにプッシュして,herokuでデプロイすればOK.
デプロイ方法は以下の記事から
https://qiita.com/tarakokko3233/items/0961933e2b9695cb561a

この記事内ではPythonのDjangoを使っているが,そこに登場するProcfile``runtime.txtは不要である.

今回は環境変数を用いなかったがherokuに環境変数を登録してソースコードには以下のように記述すれば環境変数が使用できる.

os.Getenv("KEY")

環境変数については以下の記事を参考にすること
https://qiita.com/tarakokko3233/items/bb63dbef9d91f44d3917

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5