Développement Go avec Claude Code
Découvrez développement Go avec Claude Code. Conseils pratiques et exemples de code inclus.
Go言語開発でClaude Codeを活用するメリット
GoはシンプルなAPI設計、強力な並行処理、高速なコンパイルが特徴です。Claude CodeはGoのイディオムを理解し、エラーハンドリング、ゴルーチン、チャネルなどGo特有のパターンを正確に実装できます。
Web APIの開発
> Goの標準ライブラリとchiルーターでREST APIを作成して。
> ミドルウェア、バリデーション、構造化ログも実装して。
// main.go
package main
import (
"context"
"encoding/json"
"log/slog"
"net/http"
"os"
"os/signal"
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/google/uuid"
)
type Task struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
Completed bool `json:"completed"`
CreatedAt time.Time `json:"created_at"`
}
type CreateTaskRequest struct {
Title string `json:"title"`
Description string `json:"description,omitempty"`
}
type TaskStore struct {
tasks map[string]*Task
}
func NewTaskStore() *TaskStore {
return &TaskStore{tasks: make(map[string]*Task)}
}
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
slog.SetDefault(logger)
store := NewTaskStore()
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(requestLogger)
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(30 * time.Second))
r.Route("/api/tasks", func(r chi.Router) {
r.Get("/", store.listTasks)
r.Post("/", store.createTask)
r.Route("/{id}", func(r chi.Router) {
r.Get("/", store.getTask)
r.Put("/", store.updateTask)
r.Delete("/", store.deleteTask)
})
})
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
})
srv := &http.Server{
Addr: ":8080",
Handler: r,
ReadTimeout: 10 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 60 * time.Second,
}
// Graceful shutdown
go func() {
slog.Info("Server starting", "addr", srv.Addr)
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
slog.Error("Server error", "error", err)
os.Exit(1)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
slog.Info("Shutting down server...")
if err := srv.Shutdown(ctx); err != nil {
slog.Error("Shutdown error", "error", err)
}
}
func (s *TaskStore) listTasks(w http.ResponseWriter, r *http.Request) {
tasks := make([]*Task, 0, len(s.tasks))
for _, t := range s.tasks {
tasks = append(tasks, t)
}
writeJSON(w, http.StatusOK, tasks)
}
func (s *TaskStore) createTask(w http.ResponseWriter, r *http.Request) {
var req CreateTaskRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "Invalid request body")
return
}
if req.Title == "" {
writeError(w, http.StatusBadRequest, "Title is required")
return
}
task := &Task{
ID: uuid.New().String(),
Title: req.Title,
Description: req.Description,
Completed: false,
CreatedAt: time.Now(),
}
s.tasks[task.ID] = task
writeJSON(w, http.StatusCreated, task)
}
func (s *TaskStore) getTask(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
task, ok := s.tasks[id]
if !ok {
writeError(w, http.StatusNotFound, "Task not found")
return
}
writeJSON(w, http.StatusOK, task)
}
func (s *TaskStore) updateTask(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
task, ok := s.tasks[id]
if !ok {
writeError(w, http.StatusNotFound, "Task not found")
return
}
var req struct {
Title *string `json:"title"`
Description *string `json:"description"`
Completed *bool `json:"completed"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "Invalid request body")
return
}
if req.Title != nil {
task.Title = *req.Title
}
if req.Description != nil {
task.Description = *req.Description
}
if req.Completed != nil {
task.Completed = *req.Completed
}
writeJSON(w, http.StatusOK, task)
}
func (s *TaskStore) deleteTask(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
if _, ok := s.tasks[id]; !ok {
writeError(w, http.StatusNotFound, "Task not found")
return
}
delete(s.tasks, id)
w.WriteHeader(http.StatusNoContent)
}
func writeJSON(w http.ResponseWriter, status int, data interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(data)
}
func writeError(w http.ResponseWriter, status int, message string) {
writeJSON(w, status, map[string]string{"error": message})
}
func requestLogger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
next.ServeHTTP(ww, r)
slog.Info("Request",
"method", r.Method,
"path", r.URL.Path,
"status", ww.Status(),
"duration_ms", time.Since(start).Milliseconds(),
"request_id", middleware.GetReqID(r.Context()),
)
})
}
並行処理のパターン
> 複数のAPIを並行に呼び出して結果を集約する関数を作成して。
> コンテキストによるキャンセルとタイムアウトも実装して。
// concurrent.go
package service
import (
"context"
"fmt"
"sync"
"time"
)
type AggregatedData struct {
Users []User `json:"users"`
Products []Product `json:"products"`
Orders []Order `json:"orders"`
}
func FetchDashboardData(ctx context.Context) (*AggregatedData, error) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
var (
result AggregatedData
mu sync.Mutex
wg sync.WaitGroup
errs []error
)
// ユーザー取得
wg.Add(1)
go func() {
defer wg.Done()
users, err := fetchUsers(ctx)
mu.Lock()
defer mu.Unlock()
if err != nil {
errs = append(errs, fmt.Errorf("fetch users: %w", err))
return
}
result.Users = users
}()
// 商品取得
wg.Add(1)
go func() {
defer wg.Done()
products, err := fetchProducts(ctx)
mu.Lock()
defer mu.Unlock()
if err != nil {
errs = append(errs, fmt.Errorf("fetch products: %w", err))
return
}
result.Products = products
}()
// 注文取得
wg.Add(1)
go func() {
defer wg.Done()
orders, err := fetchOrders(ctx)
mu.Lock()
defer mu.Unlock()
if err != nil {
errs = append(errs, fmt.Errorf("fetch orders: %w", err))
return
}
result.Orders = orders
}()
wg.Wait()
if len(errs) > 0 {
return &result, fmt.Errorf("partial failure: %v", errs)
}
return &result, nil
}
テーブル駆動テスト
// main_test.go
package main
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-chi/chi/v5"
)
func TestCreateTask(t *testing.T) {
tests := []struct {
name string
body map[string]interface{}
wantStatus int
}{
{
name: "valid task",
body: map[string]interface{}{"title": "Test Task"},
wantStatus: http.StatusCreated,
},
{
name: "empty title",
body: map[string]interface{}{"title": ""},
wantStatus: http.StatusBadRequest,
},
{
name: "missing title",
body: map[string]interface{}{},
wantStatus: http.StatusBadRequest,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
store := NewTaskStore()
body, _ := json.Marshal(tt.body)
req := httptest.NewRequest(http.MethodPost, "/api/tasks", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
store.createTask(rec, req)
if rec.Code != tt.wantStatus {
t.Errorf("got status %d, want %d", rec.Code, tt.wantStatus)
}
})
}
}
Summary
Claude Codeを使えば、GoのWeb API、並行処理、CLIツール、テストを効率的に開発できます。Goのイディオムであるエラーハンドリングパターンやテーブル駆動テストもClaude Codeは正確に生成します。開発の基本的な効率化については生産性を3倍にするTipsを参照してください。プロジェクトのGo規約はCLAUDE.mdに記述しておくと一貫性が保てます。
Claude Codeの詳細はAnthropic公式ドキュメントをご覧ください。Goの公式ガイドはGo公式サイトを参照してください。
Related Posts
Comment booster vos projets personnels avec Claude Code [Avec exemples]
Apprenez à accélérer considérablement vos projets de développement personnels avec Claude Code. Inclut des exemples concrets et un workflow pratique de l'idée au déploiement.
Comment automatiser le refactoring avec Claude Code
Apprenez à automatiser efficacement le refactoring de code avec Claude Code. Inclut des prompts pratiques et des patterns de refactoring concrets pour des projets réels.
Guide complet de configuration CORS avec Claude Code
Découvrez le guide complet de configuration CORS avec Claude Code. Conseils pratiques et exemples de code inclus.