everything-claude-code/docs/ja-JP/examples/go-microservice-CLAUDE.md
Claude 5a5a47e710 docs: add missing Japanese translations to complete zh-CN parity (ja-JP)
Add remaining files to match zh-CN documentation structure:
- hooks/README.md — hooks architecture and customization guide
- examples/ — 8 project CLAUDE.md templates (general, user, django, go, harmonyos, laravel, rust, saas-nextjs)
- CHANGELOG.md — version history
- the-openclaw-guide.md — OpenClaw guide (471 lines)

Total: 11 files, 2362 insertions
ja-JP now has full parity with zh-CN directory structure.
2026-05-17 02:31:40 -04:00

268 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Go マイクロサービス — プロジェクト CLAUDE.md
> PostgreSQL、gRPC、Dockerを使用したGoマイクロサービスの実世界サンプル。
> これをプロジェクトのルートにコピーしてサービスに合わせてカスタマイズしてください。
## プロジェクト概要
**スタック:** Go 1.22+, PostgreSQL, gRPC + REST (grpc-gateway), Docker, sqlc (型安全SQL), Wire (依存性注入)
**アーキテクチャ:** ドメイン、リポジトリ、サービス、ハンドラーレイヤーを持つクリーンアーキテクチャ。gRPCをプライマリトランスポートとし、外部クライアント向けにRESTゲートウェイを提供。
## 重要なルール
### Go の規約
- Effective Goと Go Code Review Comments ガイドに従う
- エラーのラッピングには `errors.New` / `fmt.Errorf``%w` を使用 — エラーに対する文字列マッチングは禁止
- `init()` 関数は使用しない — `main()` またはコンストラクターで明示的に初期化する
- グローバルな可変状態は使用しない — コンストラクター経由で依存関係を渡す
- コンテキストは最初のパラメーターにし、すべてのレイヤーを通じて伝播させること
### データベース
- すべてのクエリは `queries/` にプレーンSQLとして記述 — sqlcが型安全なGoコードを生成
- `migrations/` のマイグレーションはgolang-migrateを使用 — データベースを直接変更しない
- 複数ステップの操作には `pgx.Tx` を使用してトランザクションを使用する
- すべてのクエリはパラメータ化プレースホルダー(`$1`, `$2`)を使用 — 文字列フォーマットは禁止
### エラーハンドリング
- パニックしない、エラーを返す — パニックは本当に回復不可能な状況のみ
- コンテキストと共にエラーをラップする: `fmt.Errorf("creating user: %w", err)`
- ビジネスロジック用のセンチネルエラーを `domain/errors.go` に定義する
- ハンドラーレイヤーでドメインエラーをgRPCステータスコードにマップする
```go
// ドメインレイヤー — センチネルエラー
var (
ErrUserNotFound = errors.New("user not found")
ErrEmailTaken = errors.New("email already registered")
)
// ハンドラーレイヤー — gRPCステータスにマップ
func toGRPCError(err error) error {
switch {
case errors.Is(err, domain.ErrUserNotFound):
return status.Error(codes.NotFound, err.Error())
case errors.Is(err, domain.ErrEmailTaken):
return status.Error(codes.AlreadyExists, err.Error())
default:
return status.Error(codes.Internal, "internal error")
}
}
```
### コードスタイル
- コードやコメントに絵文字を使用しない
- エクスポートされた型と関数にはドキュメントコメントが必要
- 関数は50行以内に収める — ヘルパーを抽出する
- 複数のケースを持つすべてのロジックにはテーブル駆動テストを使用する
- シグナルチャンネルには `bool` ではなく `struct{}` を優先する
## ファイル構成
```
cmd/
server/
main.go # エントリーポイント、Wire注入、グレースフルシャットダウン
internal/
domain/ # ビジネス型とインターフェース
user.go # ユーザーエンティティとリポジトリインターフェース
errors.go # センチネルエラー
service/ # ビジネスロジック
user_service.go
user_service_test.go
repository/ # データアクセスsqlc生成 + カスタム)
postgres/
user_repo.go
user_repo_test.go # testcontainersを使用した統合テスト
handler/ # gRPC + RESTハンドラー
grpc/
user_handler.go
rest/
user_handler.go
config/ # 設定の読み込み
config.go
proto/ # Protobuf定義
user/v1/
user.proto
queries/ # sqlc用SQLクエリ
user.sql
migrations/ # データベースマイグレーション
001_create_users.up.sql
001_create_users.down.sql
```
## 主要なパターン
### リポジトリインターフェース
```go
type UserRepository interface {
Create(ctx context.Context, user *User) error
FindByID(ctx context.Context, id uuid.UUID) (*User, error)
FindByEmail(ctx context.Context, email string) (*User, error)
Update(ctx context.Context, user *User) error
Delete(ctx context.Context, id uuid.UUID) error
}
```
### 依存性注入付きサービス
```go
type UserService struct {
repo domain.UserRepository
hasher PasswordHasher
logger *slog.Logger
}
func NewUserService(repo domain.UserRepository, hasher PasswordHasher, logger *slog.Logger) *UserService {
return &UserService{repo: repo, hasher: hasher, logger: logger}
}
func (s *UserService) Create(ctx context.Context, req CreateUserRequest) (*domain.User, error) {
existing, err := s.repo.FindByEmail(ctx, req.Email)
if err != nil && !errors.Is(err, domain.ErrUserNotFound) {
return nil, fmt.Errorf("checking email: %w", err)
}
if existing != nil {
return nil, domain.ErrEmailTaken
}
hashed, err := s.hasher.Hash(req.Password)
if err != nil {
return nil, fmt.Errorf("hashing password: %w", err)
}
user := &domain.User{
ID: uuid.New(),
Name: req.Name,
Email: req.Email,
Password: hashed,
}
if err := s.repo.Create(ctx, user); err != nil {
return nil, fmt.Errorf("creating user: %w", err)
}
return user, nil
}
```
### テーブル駆動テスト
```go
func TestUserService_Create(t *testing.T) {
tests := []struct {
name string
req CreateUserRequest
setup func(*MockUserRepo)
wantErr error
}{
{
name: "valid user",
req: CreateUserRequest{Name: "Alice", Email: "alice@example.com", Password: "secure123"},
setup: func(m *MockUserRepo) {
m.On("FindByEmail", mock.Anything, "alice@example.com").Return(nil, domain.ErrUserNotFound)
m.On("Create", mock.Anything, mock.Anything).Return(nil)
},
wantErr: nil,
},
{
name: "duplicate email",
req: CreateUserRequest{Name: "Alice", Email: "taken@example.com", Password: "secure123"},
setup: func(m *MockUserRepo) {
m.On("FindByEmail", mock.Anything, "taken@example.com").Return(&domain.User{}, nil)
},
wantErr: domain.ErrEmailTaken,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
repo := new(MockUserRepo)
tt.setup(repo)
svc := NewUserService(repo, &bcryptHasher{}, slog.Default())
_, err := svc.Create(context.Background(), tt.req)
if tt.wantErr != nil {
assert.ErrorIs(t, err, tt.wantErr)
} else {
assert.NoError(t, err)
}
})
}
}
```
## 環境変数
```bash
# データベース
DATABASE_URL=postgres://user:pass@localhost:5432/myservice?sslmode=disable
# gRPC
GRPC_PORT=50051
REST_PORT=8080
# 認証
JWT_SECRET= # 本番環境ではvaultから読み込む
TOKEN_EXPIRY=24h
# オブザーバビリティ
LOG_LEVEL=info # debug, info, warn, error
OTEL_ENDPOINT= # OpenTelemetryコレクター
```
## テスト戦略
```bash
/go-test # GoのTDDワークフロー
/go-review # Go固有のコードレビュー
/go-build # ビルドエラーの修正
```
### テストコマンド
```bash
# ユニットテスト(高速、外部依存なし)
go test ./internal/... -short -count=1
# 統合テストtestcontainers用にDockerが必要
go test ./internal/repository/... -count=1 -timeout 120s
# カバレッジ付きすべてのテスト
go test ./... -coverprofile=coverage.out -count=1
go tool cover -func=coverage.out # サマリー
go tool cover -html=coverage.out # ブラウザ
# レースディテクター
go test ./... -race -count=1
```
## ECCワークフロー
```bash
# 計画
/plan "Add rate limiting to user endpoints"
# 開発
/go-test # Go固有パターンでのTDD
# レビュー
/go-review # Goのイディオム、エラーハンドリング、並行処理
/security-scan # シークレットと脆弱性
# マージ前
go vet ./...
staticcheck ./...
```
## Git ワークフロー
- `feat:` 新機能、`fix:` バグ修正、`refactor:` コード変更
- `main` からフィーチャーブランチを切り、PRが必要
- CI: `go vet`, `staticcheck`, `go test -race`, `golangci-lint`
- デプロイ: CIでDockerイメージをビルドし、Kubernetesにデプロイ