1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

主要なアーキテクチャパターン

1. MVCアーキテクチャ

  • 特徴
    • Model(データ)、View(表示)、Controller(制御)の3層構造
  • メリット
    • 責務が明確に分離され、保守性が高い
    • コードの再利用性が向上
    • テストが容易
  • デメリット
    • Model、Controllerが肥大化しやすい

2. レイヤードアーキテクチャ

  • 特徴
    • プレゼンテーション層、ビジネスロジック層、データアクセス層などの階層構造
  • メリット
    • 関心事の分離が明確
    • 各層の独立した開発が可能
    • 保守性とスケーラビリティが高い
  • デメリット
    • 層間の依存関係管理が複雑になる可能性
    • パフォーマンスへの影響(層間通信のオーバーヘッド)

3. クリーンアーキテクチャ

  • 特徴
    • ドメイン中心の設計、依存関係の方向が内側に向く
  • メリット
    • ビジネスロジックが外部要因から保護される
    • テスタビリティが高い
    • フレームワークに依存しない設計
  • デメリット
    • 学習曲線が急
    • 小規模プロジェクトでは複雑すぎる可能性

実装例

MVCアーキテクチャの実装例

model/user.go
package model

type User struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}
view/user_view.go
package view

import (
	"encoding/json"
	"go-cs/model"
)

type UserView struct {
	User *model.User
}

func (v *UserView) RenderJSON() ([]byte, error) {
	return json.Marshal(v.User)
}
controller/user_controller.go
package controller

import (
	"database/sql"
	"encoding/json"
	"net/http"
	"strconv"

	"go-cs/service"
)

type UserController struct {
	userService *service.UserService
}

func NewUserController(userService *service.UserService) *UserController {
	return &UserController{userService: userService}
}

func (c *UserController) GetUser(w http.ResponseWriter, r *http.Request) {
	id, err := strconv.Atoi(r.PathValue("id"))
	if err != nil {
		http.Error(w, "Invalid user ID", http.StatusBadRequest)
		return
	}

	user, err := c.userService.GetUser(id)
	if err != nil {
		if err == sql.ErrNoRows {
			http.Error(w, "User not found", http.StatusNotFound)
			return
		}
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(user)
}
service/user_service.go
package service

import (
	"database/sql"

	"go-cs/model"
)

type UserService struct {
	db *sql.DB
}

func NewUserService(db *sql.DB) *UserService {
	return &UserService{db: db}
}

func (s *UserService) GetUser(id int) (*model.User, error) {
	user := &model.User{}
	err := s.db.QueryRow("SELECT id, name, email FROM users WHERE id = ?", id).
		Scan(&user.ID, &user.Name, &user.Email)
	if err != nil {
		return nil, err
	}
	return user, nil
}
main.go
package main

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

	"go-cs/controller"
	"go-cs/service"

	_ "github.com/mattn/go-sqlite3"
)

func main() {
	db, err := sql.Open("sqlite3", "./users.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// テーブル作成
	createTable(db)

	// サンプルデータ挿入
	insertSampleData(db)

	// 依存関係の注入
	userService := service.NewUserService(db)
	userController := controller.NewUserController(userService)

	// ルーティング
	http.HandleFunc("GET /users/{id}", userController.GetUser)

	log.Println("Server starting on :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func createTable(db *sql.DB) {
	query := `
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT NOT NULL UNIQUE
    );`

	_, err := db.Exec(query)
	if err != nil {
		log.Fatal(err)
	}
}

func insertSampleData(db *sql.DB) {
	_, err := db.Exec(`INSERT INTO users (name, email) VALUES (?, ?)`,
		"Tanaka Taro", "taro@example.com")
	if err != nil {
		log.Fatal(err)
	}
}
curl http://localhost:8080/users/1

{"id":1,"name":"Tanaka Taro","email":"taro@example.com"}
curl http://localhost:8080/users/123

User not found
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?