課題1: Go言語の理解と環境構築
課題概要
この課題では、Go言語の設計思想を深く理解し、実際の開発環境を構築します。なぜGoが現代のソフトウェア開発で重要なのか、他の言語とどう違うのかを実践を通じて学びます。
マンダトリー要件
要件1: Go開発環境の構築
公式サイト(https://go.dev/)から最新版のGoをインストールし、以下を確認してください:
# Goのバージョン確認
go version
# 出力例: go version go1.21.5 darwin/amd64
環境変数が正しく設定されていることを確認:
# GOPATH確認
go env GOPATH
# GOROOTの確認
go env GOROOT
要件2: Hello, World!プログラム
最初のGoプログラムを作成します。
ファイル: hello.go
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
実行方法:
# 直接実行
go run hello.go
# ビルドして実行
go build hello.go
./hello
要件3: 設計哲学の分析レポート
以下の質問に対して、具体的なコード例を交えながら回答してください(各200-300文字):
Q1: Goに三項演算子(condition ? true_value : false_value)がない理由を、設計哲学の観点から説明してください。
Q2: Goのエラー処理(戻り値として返す方式)と、JavaやPythonの例外処理(try-catch)の違いについて、メリット・デメリットを説明してください。
Q3: 以下のC++コードをGoで書き換え、Goのどのような特徴が活かされているか説明してください:
#include <thread>
#include <iostream>
void task(int id) {
std::cout << "Task " << id << std::endl;
}
int main() {
std::thread t1(task, 1);
std::thread t2(task, 2);
t1.join();
t2.join();
return 0;
}
要件4: 比較プログラムの作成
C言語、Python、Goで同じ処理を実装し、コンパイル時間・実行時間・バイナリサイズを比較してください。
処理内容: 1から1000000までの数値の合計を計算する
C言語版 (sum.c):
#include <stdio.h>
int main() {
long long sum = 0;
for (int i = 1; i <= 1000000; i++) {
sum += i;
}
printf("Sum: %lld\n", sum);
return 0;
}
Python版 (sum.py):
sum_value = sum(range(1, 1000001))
print(f"Sum: {sum_value}")
Go版 (sum.go):
package main
import "fmt"
func main() {
sum := 0
for i := 1; i <= 1000000; i++ {
sum += i
}
fmt.Printf("Sum: %d\n", sum)
}
測定方法:
# C言語
time gcc sum.c -o sum_c
time ./sum_c
ls -lh sum_c
# Python
time python3 sum.py
# Go
time go build sum.go
time ./sum
ls -lh sum
比較表を作成してください:
| 言語 | コンパイル時間 | 実行時間 | バイナリサイズ |
|---|---|---|---|
| C | |||
| Go | |||
| Python | - (インタプリタ) | - |
期待される出力
Hello, World!の出力
Hello, Go!
合計計算の出力(全言語共通)
Sum: 500000500000
ボーナス課題
> ボーナス: これらはオプションです。マンダトリー部分が完了してから取り組んでください。
ボーナス1: 並行処理のパフォーマンス比較
goroutineの軽量性を実証するプログラムを作成してください。
要求:
- 1000個のgoroutineを起動し、それぞれが1から1000までの数値の合計を計算
- チャネルで結果を集約
- 実行時間を測定
package main
import (
"fmt"
"sync"
"time"
)
func calculateSum(id int, wg *sync.WaitGroup, results chan<- int) {
defer wg.Done()
sum := 0
for i := 1; i <= 1000; i++ {
sum += i
}
results <- sum
}
func main() {
start := time.Now()
var wg sync.WaitGroup
results := make(chan int, 1000)
for i := 0; i < 1000; i++ {
wg.Add(1)
go calculateSum(i, &wg, results)
}
wg.Wait()
close(results)
total := 0
for result := range results {
total += result
}
elapsed := time.Since(start)
fmt.Printf("Total: %d\n", total)
fmt.Printf("Time: %v\n", elapsed)
}
同じ処理をPythonのスレッドで実装し、実行時間を比較してください。
ボーナス2: クロスコンパイルの実践
以下のプラットフォーム向けにビルドし、バイナリサイズを比較してください:
# Linux (amd64)
GOOS=linux GOARCH=amd64 go build -o hello_linux hello.go
# Windows (amd64)
GOOS=windows GOARCH=amd64 go build -o hello_windows.exe hello.go
# macOS (arm64, Apple Silicon)
GOOS=darwin GOARCH=arm64 go build -o hello_mac_arm hello.go
# Raspberry Pi (ARM)
GOOS=linux GOARCH=arm GOARM=7 go build -o hello_pi hello.go
バイナリサイズ比較表:
| プラットフォーム | バイナリサイズ | 備考 |
|---|---|---|
| Linux (amd64) | ||
| Windows (amd64) | ||
| macOS (arm64) | ||
| Raspberry Pi |
ボーナス3: Goのツールチェーン探索
Goの標準ツールを使って、コード品質を向上させてください:
# コードフォーマット
go fmt hello.go
# 静的解析
go vet hello.go
# コードのリント(golangci-lintをインストール)
golangci-lint run hello.go
# コードカバレッジ(テストコードがある場合)
go test -cover
# ベンチマーク
go test -bench=.
それぞれのツールの役割と出力結果を説明するレポートを作成してください。
評価基準
| 項目 | 配点 | 詳細 |
|---|---|---|
| 環境構築 | 20点 | Goが正しくインストールされ、動作確認ができている |
| Hello, World! | 10点 | 正しく動作するプログラムが書けている |
| 設計哲学分析 | 30点 | 各質問に対して具体的なコード例と共に説明されている |
| 比較プログラム | 20点 | 3言語で実装し、測定結果が表にまとめられている |
| **ボーナス1** | 10点 | goroutineの並行処理が正しく実装されている |
| **ボーナス2** | 5点 | 複数プラットフォーム向けにビルドできている |
| **ボーナス3** | 5点 | Goツールチェーンの活用方法を理解している |
提出方法
以下のファイルを提出してください:
submission/
├── hello.go
├── sum.go
├── analysis.md # 設計哲学の分析レポート
├── comparison.md # 言語比較の結果
└── bonus/ # ボーナス課題(オプション)
├── concurrent.go
├── cross_compile.md
└── tools_report.md
ヒント
go envコマンドで現在の設定を確認できますsync.WaitGroupでgoroutineの完了を待つgo tool dist listで確認できるgo helpで利用可能なコマンドの一覧が表示されます