Goにおけるサービス層とデータベース接続の最適な設計パターン
こんにちは!フリーランスエンジニアのこたろうです。
サービス層の設計とデータベース操作について、実践で得た知見を共有します。
サービス層の責務
- ユーザーリクエストのデータベース操作への変換
- ビジネスロジックの実装
- データベースから取得したデータのハンドラ層用整形
非推奨パターンと推奨パターン
非推奨:頻繁なDB接続
// 非推奨パターン
func (s *Service) GetPost(id int) (*Post, error) {
db, err := sql.Open("postgres", "connection-string")
if err != nil {
return nil, err
}
defer db.Close()
// ...
}
推奨:構造体でのDB保持
package services
import "database/sql"
// サービス構造体の定義
type MyAppService struct {
db *sql.DB
}
// コンストラクタ
func NewMyAppService(db *sql.DB) *MyAppService {
return &MyAppService{db: db}
}
// サービスメソッド
func (s *MyAppService) PostArticleService(article models.Article) (models.Article, error) {
newArticle, err := repositories.InsertArticle(s.db, article)
if err != nil {
return models.Article{}, err
}
return newArticle, nil
}
設計のポイント
- sql.DBの接続は初期化時に1回のみ実行
- DBコネクションをサービス構造体で保持・再利用
- サービス層はデータ整形とビジネスロジックに集中
- コネクション管理の一元化
この設計により、保守性の高い効率的なアプリケーション構造を実現できます。
参考文献
-『Goで作るはじめてのWebアプリケーション改訂版』技術書典