😊
📝 Go vs C# Todo App を Docker化して比較してみた!
はじめに
エンジニア4ヶ月目のSomeです!
前回、業務で使っているC#でTodoアプリを作ってDocker化してみました。
- 前回の記事: C# TodoアプリのDocker化
今回はGo言語とDockerを勉強中なので、同じ機能のTodoアプリをGoで作って、C#版と比較してみました!
結果が想像以上にすごかったので、共有します😊
🔧 環境
- MacBook Air (M3)
- メモリ: 16GB
- Go: 1.21(勉強中)
- .NET: 8.0(業務で使用)
**⚡ 結果まとめ - **
| 項目 | C# | Go | 差 |
|---|---|---|---|
| 📦 イメージサイズ | 379MB | 11.5MB | 33倍小さい! |
| 🚀 処理速度 | 407 req/s | 2,572 req/s | 6倍速い! |
| ⚡ 応答時間 | 24.56ms | 2.3ms | 10倍速い! |
| 💾 メモリ使用量 | 52MB | 22MB | 半分以下! |
| 📝 コード量 | 500行+ | 150行 | 1/3! |
正直、ここまで差が出るとは思ってませんでした...😅
🛠️ 作ったアプリ
機能
両方とも同じ機能を実装しました:
- ✅ Todo追加: タイトル入力
- ✅ Todo一覧: リスト表示
- ✅ 完了切り替え: チェックボックス
- ✅ Todo削除: 削除ボタン
C#版(前回作成)
ASP.NET Core Razor Pagesで作りました。
Models/Todo.cs # データモデル
Data/TodoContext.cs # データベース設定
Pages/Index.cshtml # メインページ
Pages/Todos/Create.cshtml # 作成ページ
Pages/Todos/Edit.cshtml # 編集ページ
Pages/Todos/Delete.cshtml # 削除ページ
Program.cs # メイン設定
合計: 15ファイル、500行くらい
Go版(今回作成)
Go初心者なので、あえてシンプルに標準ライブラリだけで作りました。
// main.go - これだけ!
package main
import (
"html/template"
"net/http"
// など
)
type Todo struct {
ID int
Title string
Completed bool
}
// CRUD関数 + HTTPハンドラー + HTMLテンプレート
// 全部で150行くらい
感想: Goの方がシンプルで分かりやすいかも!?
🐳 Docker化してみた
なぜDockerで比較?
- 実際の環境に近い状態で測定したかった
- メモリやCPUの使用量を正確に測りたかった
- Dockerを覚えたばかりなので練習も兼ねて
C#のDockerfile
# マルチステージビルド
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/out .
# セキュリティ設定など...
ENTRYPOINT ["dotnet", "SimpleTodoAPI.dll"]
GoのDockerfile
# マルチステージビルド
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .
CMD ["./main"]
Docker初心者の感想: Goの方がDockerfileもシンプルでした!
📊 性能測定してみた
Apache Benchで測定
初めて使いましたが、Webサイトの性能測定の定番ツールらしいです。
基本テスト(同時接続10人)
# 1000回リクエスト、同時接続10人
ab -n 1000 -c 10 http://localhost:8080/
C#の結果
Time taken for tests: 2.456 seconds
Requests per second: 407.14 [#/sec]
Time per request: 24.56 [ms]
Goの結果
Time taken for tests: 0.529 seconds ← C#の1/5!
Requests per second: 1890.23 [#/sec] ← C#の4.6倍!
Time per request: 5.290 [ms] ← C#の1/5!
驚き: Goめちゃくちゃ速い...😳
高負荷テスト(同時接続100人)
# 10000回リクエスト、同時接続100人
ab -n 10000 -c 100 http://localhost:8080/
C#の結果
Time taken for tests: 24.56 seconds
Requests per second: 407.14 [#/sec]
Time per request: 245.6 [ms] ← 10倍遅くなった
Goの結果
Time taken for tests: 3.888 seconds ← C#の1/6!
Requests per second: 2572.10 [#/sec] ← C#の6.3倍!
Time per request: 38.879 [ms] ← C#の1/6!
学び: 負荷が高くなってもGoは安定!
レスポンス時間の詳細
# 10回測定してみた
for i in {1..10}; do
curl -o /dev/null -s -w "時間: %{time_total}s\n" http://localhost:8080/
done
Goの結果:
時間: 0.002787s (2.8ms)
時間: 0.001781s (1.8ms)
時間: 0.002051s (2.1ms)
...
平均: 2.3ms ← 超安定!
💾 メモリとCPUの使用量
測定方法
# Dockerコンテナのリソース使用量を確認
docker stats コンテナ名 --no-stream
結果比較
C#(前回測定)
# 普通の状態
CPU: 0.8% → 0.1%
メモリ: 52MB
# 負荷テスト中
CPU: 45.2%
メモリ: 67.3MB
Go(今回測定)
# 普通の状態
CPU: 0.00% ← ほぼゼロ!
メモリ: 10MB
# 負荷テスト後
CPU: 0.00%
メモリ: 22MB ← C#の1/3
感想: Goのリソース効率すごすぎる...
🤔 なぜこんなに差が出るの?
Go初心者なりに調べてみました:
C#の特徴
- .NET Runtimeが必要(重い)
- 多機能で便利だけど、その分重い
- JIT(Just-In-Time)コンパイル
Goの特徴
- 実行ファイル1つで動く(軽い)
- シンプルで必要最小限
- 事前にコンパイル済み
初心者の理解: C#は高機能だけど重い、Goはシンプルだけど軽くて速い
💰 実際のコストへの影響
イメージサイズの差
C#: 379MB
Go: 11.5MB
差: 33倍!
これって、クラウドで動かすときの転送コストに直結しますよね...
簡単な計算
月100回デプロイする場合:
C#: 379MB × 100回 = 37.9GB
Go: 11.5MB × 100回 = 1.15GB
転送量: 97%削減!
サーバーコスト
同じサーバーで動かす場合:
C#: 1台で407 req/s
Go: 1台で2,572 req/s
→ Goなら6分の1のサーバー台数で済む
学び: 性能差は直接お金に影響する!
😅 正直な感想
予想していたこと
- Goの方が少し速いかな?
- イメージサイズも少し小さいかな?
実際の結果
- 6倍速い ← 予想外
- 33倍小さい ← 嘘だろ...
- メモリ半分以下 ← すごすぎ
学習した教訓
- 言語の選択って大事: 用途に応じて選ぶべき
- Docker化すると違いがはっきり: 実測って重要
- シンプルの威力: 複雑 ≠ 良い
🤷♂️ どっちを使えばいいの?
初心者なりの判断基準:
Goを選ぶ場面
- API作る時: 速くて軽い
- クラウドで動かす時: コスト削減
- シンプルなWebアプリ: 学習コストも低い
C#を選ぶ場面
- 複雑な業務システム: 豊富な機能
- チーム開発: ツールが充実
- Windows環境: やっぱり相性良い
個人的な感想
- 学習用: Goの方が分かりやすい
- 業務用: C#の方が安心(今のところ)
- 趣味: Goが楽しい!w
📝 実際に実行したコマンド
# Docker化
docker build -t go-todo-app .
docker run -d -p 8080:8080 --name go-todo-app go-todo-app
# 性能測定
ab -n 1000 -c 10 http://localhost:8080/
ab -n 10000 -c 100 http://localhost:8080/
# レスポンス時間測定
for i in {1..10}; do
curl -o /dev/null -s -w "時間: %{time_total}s\n" http://localhost:8080/
done
# リソース確認
docker stats go-todo-app --no-stream
# イメージサイズ確認
docker images | grep todo
🚀 次にやってみたいこと
- データベース接続: PostgreSQLを使った場合の比較
- 認証機能: JWT認証の実装と性能比較
- フレームワーク比較: GinやEchoを使った場合
- 本格的な監視: PrometheusとGrafanaでメトリクス収集
📚 参考にした資料
- GitHub: 今回のコード
- 前回の記事: C# TodoアプリのDocker化
- Go公式: https://golang.org/
- Docker公式: https://docs.docker.com/
💭 まとめ
率直な感想: ここまで差が出るとは思いませんでした!
今回の発見:
- Goの性能は本当にすごい(33倍、6倍、10倍...)
- Dockerで測定すると違いがはっきり分かる
- 言語選択は性能とコストに直結する
学んだこと:
- 実際に測定することの大切さ
- 適材適所で言語を選ぶ重要性
- シンプルな実装の威力
次のステップ:
Go の勉強をもっと頑張って、実際の開発でも使えるようになりたいです!
4ヶ月目エンジニアの正直な感想: C#も好きだけど、Goも面白い!
適材適所で使い分けられるエンジニアになりたいです😊
読んでくださってありがとうございました!
同じような初心者の方の参考になれば嬉しいです 🙌
Discussion