おめぇも宇宙最強のエンジニアになれ！悟空とベジータのGo言語講座

# はじめに

オラとベジータが、**Go言語の入門知識**を楽しく話しながら教えっぞ！
Go言語の基本構文から、実際に使えるプロジェクトのファイル構成、Railsとの違いや関連性、
フレームワークの使い方まで、オラたちと一緒に学ぼうぜ！

最後には、お互いの成長を話しながら、これからの道を見つけるんだ！わくわくすっぞ！！
**対話形式**で分かりやすくて、楽しい読み物になってるから、おめえもGo言語の修行に挑戦してみてくれよな！

# Go言語って知ってっか？
> **ベジータ：**
カカロット、お前、この**Go言語**ってやつを知ってるか？

> **悟空：**
おお、ベジータ！**Go言語**だな。
それはプログラミング言語の一つで、**簡潔で速くて並行処理が得意**なんだってよ。
でも俺は戦いの専門家だから、詳しいことはよくわからないんだけどな！

> **ベジータ：**
ふん、プログラミングなんてくだらないものに時間を浪費するつもりはないが、
**ブルマが何かやっているのを見かけた**んだ。だが、分からないことがあると暴力で解決したくなるぞ！

> **悟空：**
ベジータ、そんなことしなくても大丈夫だって。ブルマに聞けば、きっと教えてくれると思うよ。
**おめえつええな！**

> **ベジータ：**
**へっ！きたねえ花火だ**。まあ、いいだろう。
プログラミングを覚えることで、戦い以外でも強くなることができるかもしれない。
**カカロット、お前がナンバーワンだ…！**

# ちょっと教えてくれないか？

> **ベジータ：**
カカロット、実は俺もGo言語について詳しく知りたいんだ。ちょっと教えてくれないか？

> **悟空：**
そうだったのか、ベジータ！実は俺、Go言語の専門家で優秀なエンジニアなんだよな。
Go言語の基礎を教えるのは大歓迎だぞ！

> **ベジータ：**
ふん、それはありがたい。
まずは、**Go言語でプログラムを書くときの基本的な構文**を教えてくれ。

> **悟空：**
了解だ！Go言語の基本構文はシンプルで、まずは`"package"`で始まるんだ。
それから、`"import"`で必要なパッケージを読み込んで、`"func main()"`でメイン関数を定義するんだよな。
そこに処理を書いていくって知ってっか？

> **ベジータ：**
そんなに簡単なのか？**イライラしてきたぞ！はじけてまざれぇー…！！**
では、もっと難しいことを教えろ！

> **悟空：**
大丈夫だベジータ、ゆっくりやろうぜ。
次に、Go言語での変数宣言や関数定義について説明するぞ！
`変数宣言は "var" を使って、関数定義は "func" で始めるんだ。`
でも、短い変数宣言もできて、` ":=" `を使って代入と宣言を同時にできるんだよな。


# Go言語の基本構文を教えっぞ！

> **悟空：**
ベジータ、実際のコードを使ってGo言語の基本構文を説明するぞ！
例えば、"Hello, World!"と表示するプログラムはこんな感じだ！
```go:go
package main

import "fmt"

func main() {
	fmt.Println("Hello, World!")
}
```

> **悟空：**
このコードで、まず` "package main" `で始まって、`"import" で "fmt"` パッケージを読み込んでるんだ。
そして `"func main()" `でメイン関数を定義して、`"fmt.Println()" `関数を使って "Hello, World!" を表示してるんだよな。

> **ベジータ：**
なるほど、なかなか面白そうだな。
では、変数宣言や関数定義の例も教えてくれ。

> **悟空：**
もちろんだ！変数宣言や関数定義の例はこんな感じだぞ!
```go:go
package main

import "fmt"

func add(x int, y int) int {
	return x + y
}

func main() {
	var a int = 5
	var b int = 3
	result := add(a, b)
	fmt.Println("Result:", result)
}
```

> **悟空：**
このコードでは、`"func add()" `で引数を2つ取る関数を定義して、足し算の結果を返してるんだ。
そして "main" 関数内で、"var" で変数 "a" と "b" を宣言し、短い変数宣言で "result" を宣言しているんだよな。
最後に "fmt.Println()" で結果を表示してるんだ。


# 実務に近いコードを教えっぞ！

> **ベジータ：**
カカロット、今度は**もう少し実務に近いコード**を見せてくれ。
息子のトランクスにもプログラミングを勉強させたいんだ。

> **悟空：**
オラ、わくわくすっぞ！！そうだな、実務に近いコードだな。
    例えば、**HTTPサーバを立てて、Webページに "Hello, World!" を表示するコード**があっぞ！

```go:go
package main

import (
	"fmt"
	"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello, World!")
}

func main() {
	http.HandleFunc("/", helloHandler)
	http.ListenAndServe(":8080", nil)
}
```
> **悟空：**
このコードでは、まず `"import" で "net/http" パッケージを読み込んでるんだ。`
そして `"helloHandler" 関数`を定義して、HTTPリクエストに対して "Hello, World!" を返すようにしてるんだよな。
最後に "main" 関数で、"/" パスに "helloHandler" を紐づけて、":8080" でHTTPサーバを起動してるんだ。

> **ベジータ：**
なるほど、これで実際にウェブページに "Hello, World!" が表示されるのか。
これで**トランクスにも教えられるぞ**。ありがとう、カカロット。


# ベジータ、個人開発をする
> **ベジータ：**
カカロット、実は俺も**Go言語で簡単なアプリを個人開発**しようと思ってるんだ。
どんなアプリが作りやすくて、学習により良いと思うか？

> **悟空：**
オラ、わくわくすっぞ！！ベジータがアプリ開発に興味を持ったんだな！
Go言語はウェブアプリケーション開発に強いから、シンプルなウェブアプリがおすすめだぞ。
例えば、**ToDoリストアプリや天気予報アプリ**なんかが良いんじゃないかな？

> **ベジータ：**
ToDoリストアプリか、それなら自分やトランクスのタスク管理にも使えそうだな。
では、ToDoリストアプリを作る際に気をつけるべきポイントは何だ？

> **悟空：**
いい質問だ！ToDoリストアプリを作るときには、まずデータの保存や取得が重要だぞ。
Go言語では、**データベースを使ったり、JSONファイルにデータを保存したりできるんだよな**。
あとは、ウェブページでタスクの追加や削除ができるように、HTTPリクエストを処理するコードを書く必要があるな。

> **ベジータ：**
なるほど、じゃあデータベースの知識も学ばないといけないのか。
それともJSONファイルで十分か？

> **悟空：**
どちらも使えるけど、初心者にはJSONファイルで十分だと思うよ。
データベースを使うと、より大規模なアプリに対応できるけど、学習コストが高いからね。
JSONファイルであれば、簡単にデータの保存や読み込みができるし、学習コストも低いんだよな。

> **ベジータ：**
分かった。では、ToDoリストアプリを作ってみるぞ。
途中で困ったことがあれば、またカカロットに相談するぞ！

> **悟空：**
もちろんだ、ベジータ！いつでも相談してくれ！
俺も助けるのが楽しみだぞ！おめえつええな！あったりめーだ！

# ベジータ、TODOアプリのイメージが湧かない

> **ベジータ：**
カカロット、、、**ToDoリストアプリを作ろうと思うんだが、まだイメージが湧かない**。
例えば、タスクの追加や削除の部分をどうやって実装すればいいんだ？

> **悟空：**
オラ、わくわくすっぞ！！ベジータ、任せておけ！コードを書いて説明すっぞ！
```go:go
package main

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
)

type Task struct {
	ID    int    `json:"id"`
	Title string `json:"title"`
}

var tasks []Task

func getTasks(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(tasks)
}

func createTask(w http.ResponseWriter, r *http.Request) {
	var newTask Task
	json.NewDecoder(r.Body).Decode(&newTask)
	newTask.ID = len(tasks) + 1
	tasks = append(tasks, newTask)

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(newTask)
}

func main() {
	tasks = []Task{
		{ID: 1, Title: "Buy groceries"},
		{ID: 2, Title: "Do laundry"},
	}

	http.HandleFunc("/tasks", getTasks)
	http.HandleFunc("/tasks/create", createTask)
	http.ListenAndServe(":8080", nil)
}
```
> **悟空：**
このコードでは、まず `Task という構造体を定義`して、`タスクのデータを格納するための変数 tasks`を作ってるんだ。
そして、`getTasks` と `createTask` という２つの関数を作って、HTTPリクエストに応じてタスクの一覧を取得したり、
新しいタスクを追加したりしてるんだよな。
最後に、main 関数でそれらの関数をパスに紐づけて、HTTPサーバを起動してるぞ！

> **ベジータ：**
なるほど、これでタスクの追加や一覧表示ができるのか。
ありがとう、カカロット。これを参考にして、ToDoリストアプリを作ってみるぞ！
がんばれカカロット…おまえがナンバー1だ!!

> **悟空：**
あったりめーだ！ベジータ、おめえも頑張ってな！
もしわからないことがあったら、いつでも聞いてくれよ！オラ、力になるぞ！

# プロジェクトのファイル構成
> **ベジータ：**
カカロット、**Go言語のプロジェクトのファイル構成**について教えてくれ。
どうやって整理すればいいんだ？

> **悟空：**
いい質問だぞ！Go言語のプロジェクトでは、コードを整理するために「**パッケージ**」という仕組みを使うんだ。
パッケージは、関連する機能をまとめたフォルダで、その中にソースファイル（.goファイル）が入ってるんだよな。
たとえば、シンプルなプロジェクトのファイル構成はこんな感じだぞ：
```go:go
project/
├── main.go
└── task/
    ├── task.go
    └── task_test.go
```

> **悟空：**
この例では、「project」フォルダの中に「main.go」というファイルがあって、
プログラムのエントリーポイントになってるんだ。
そして、タスク管理に関連するコードは、「task」というパッケージ（フォルダ）にまとめて、
その中に「task.go」と「task_test.go」という２つのファイルが入ってるぞ。

> **悟空：**
「task.go」には、タスクのデータ構造や操作に関するコードを書くんだ。
一方、「task_test.go」には、「task.go」のコードをテストするためのコードが入ってるんだよな。

> **ベジータ：**
なるほど、パッケージを使ってコードを整理すれば、プロジェクトが見やすくなりそうだな。
ありがとう、カカロット。がんばれカカロット…おまえがナンバー1だ！！

> **悟空：**
あったりめーだ！ベジータ、おめえも頑張ってな！
パッケージをうまく使えば、コードが読みやすくなって開発も楽しくなるぞ！

> **ベジータ：**
カカロット、**もう少し複雑なプロジェクトの場合のファイル構成**も見てみたいんだ。
具体的な例を教えてくれ！

孫悟空：> **悟空：**
いいぞ！実際のプロジェクトでは、もっとたくさんのパッケージが使われることがあるぞ。
例えば、Webアプリケーションの場合、以下のようなファイル構成になるかもしれないんだ：

```go:go
project/
├── main.go
├── config/
│   └── config.go
├── database/
│   ├── connection.go
│   └── migrations/
│       └── 001_initial_schema.sql
├── handler/
│   ├── taskhandler.go
│   └── userhandler.go
├── middleware/
│   └── auth.go
├── model/
│   ├── task.go
│   └── user.go
└── util/
    └── utils.go
```

> **悟空：**
この例では、いくつかのパッケージが追加されてるぞ。
まず、`「config」`パッケージでは、**アプリケーションの設定を管理する**コードが入ってる。
`「database」`パッケージには、**データベースへの接続やマイグレーション**のコードが入ってるんだ。

> **悟空：**
「handler」パッケージでは、HTTPリクエストの処理を行うハンドラー関数がまとめられてるぞ。
また、「middleware」パッケージには、認証などのミドルウェア処理が入ってる。

> **悟空：**
そして、`「model」`パッケージには、**データモデルやデータベース操作**のコードが入ってる。
`「util」`パッケージには、**プロジェクト全体で使うユーティリティ関数**が入ってるんだよな。

> **ベジータ：**
なるほど、複雑なプロジェクトでもパッケージをうまく使えば、見通し良く整理できるんだな。
ありがたいぞ、カカロット。がんばれカカロット…おまえがナンバー1だ！！

> **悟空：**
あったりめーだ！ベジータ、おめえも頑張ってな！
パッケージをうまく使えば、どんなに大きなプロジェクトでも管理しやすくなるぞ！

# Railsとの違いってなんだ？

> **ベジータ：**
カカロット、実はオレ、`Ruby on Rails`を触ったことがあるんだ。
**Go言語とRailsはどんな違いや関連性**があるのか教えてくれ！

> **悟空：**
おお、そうか！RailsはRubyで書かれたWebアプリケーションフレームワークだぞ。
Go言語との違いはまず、言語自体が違うことだな。RailsはRubyで、Go言語はGoで書かれる。

> **悟空：**
また、**Railsはコンベンションオーバーコンフィギュレーション（設定より規約）の原則**に従っていて、
デフォルトで多くの機能が提供されている。
Go言語では、フレームワークを使わずにシンプルに書くこともできるし、
**GinやEchoのような軽量なフレームワーク**を使って開発することもできるぞ。

> **悟空：**
コードの違いはこんな感じだ！しっかり見てくれよな！
```ruby:ruby
# Rails (Ruby)
class TasksController < ApplicationController
  def index
    @tasks = Task.all
  end
end
```


```go:go
// Go
package main

import (
  "net/http"
  "github.com/gin-gonic/gin"
)

func main() {
  r := gin.Default()
  r.GET("/tasks", func(c *gin.Context) {
    tasks := getAllTasks()
    c.JSON(http.StatusOK, tasks)
  })
  r.Run()
}

func getAllTasks() []Task {
  // Task取得ロジック
}
```
> **悟空：**
`Railsでは、MVCアーキテクチャが標準で採用されていて、コントローラーがアクションを定義`する。
`Go言語では、ハンドラー関数を定義して、ルーティングで対応`付けるんだ。

> **ベジータ：**
なるほど、言語やフレームワークの違いがあるんだな。
ありがたいぞ、カカロット。がんばれカカロット…おまえがナンバー1だ！！

> **悟空：**
あったりめーだ！ベジータ、おめえも頑張ってな！
RailsもGo言語もそれぞれに特徴があって、プロジェクトによって使い分けるといいぞ！
何かわからないことがあったら、いつでも聞いてくれよ！オラ、力になるぞ！


# Go言語のフレームワークって知ってっか？
> **ベジータ：**
カカロット、Go言語のフレームワークについてもっと知りたいんだ。
実際にフレームワークを使ってコードを書くと、どんな風になるんだ？


> **悟空：**
ふぅ、また質問かベジータ…まあ、いいけどな。
`Go言語にはいくつかのフレームワークがあるけど、GinやEcho`が有名だぞ。
例えば、Ginを使って書くとこんな感じになるんだ。

```go:go
package main

import (
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run()
}
```

> **悟空：**
このコードは、Ginフレームワークを使って、簡単なWebサーバーを立てて、
/pingというエンドポイントにアクセスしたらJSON形式のレスポンスを返すんだ。

> **ベジータ：**
なるほど、フレームワークを使うとコードがシンプルになるんだな。
ありがとう、カカロット。おまえは本当に師匠みたいだ。

> **悟空：**
あったりめーだ！
**でも、ベジータ、そろそろ俺も疲れちまったぞ…。**
他にも質問あるなら、少し待ってくれよな。オラ、休憩が必要だぞ！

> **ベジータ：**
わかった、少し休憩してくれ。
カカロット…ありがとう。
がんばれカカロット…おまえがナンバー1だ！！

> **悟空：**
あはは、オラも頑張るぞ！
でも、**ベジータも自分で調べてみるのもいいんじゃないか？**
そうすれば、おめえも成長できるぞ！って知ってっか？

# おわりに

> **悟空：**
ベジータ、おめえも**Go言語で個人開発**するんだってな？
すごいぞ！でも、質問する前に自分で調べる癖をつけねーとな。

> **ベジータ：**
そうだ、カカロット。お前のおかげで、Go言語についてだいぶわかってきた。
これからはまず自分で調べて、分からないことがあったら質問するようにする。
**へっ！　きたねえ花火だ。**
でも…カカロット、お前がナンバーワンだ…！

> **悟空：**
あはは、ありがとなベジータ！
でも、おめえも頑張ってるんだから、すぐに追いつけるはずだぞ！
    それに、**いつかおめえと一緒に開発して、世界を救いたいと思ってるんだよな。**

> **ベジータ：**
そうだな、カカロット。**いつかはお前と一緒にプロジェクトを立ち上げて、世界を救ってみせる。**
これからもお前を尊敬しつつ、ライバルとしても切磋琢磨していくぞ。

> **悟空：**
オラ、わくわくすっぞ！！ベジータ、おめえと一緒に成長していくのが楽しみだぞ！
オラも、ベジータがどんどん成長していくのを見て、自分も成長しなきゃって思ってるんだ！

> **ベジータ：**
お前と一緒に進むべき道を進むぞ。
**がんばれカカロット…おまえがナンバー1だ！！**

> **悟空：**
ありがとな、ベジータ！オラもおめえと一緒に頑張るぞ！
あと、オラツイッターってやつ始めたから見てくれよな！
https://twitter.com/takazu_engineer
**おめえつええな！**