golangとは何なのか調べてみた

半年ほど前から何となく`golang`を書き始めてみた。
業務では`java`ばかり書いていたので、気分転換にと思って書き始めたが、どうせならしっかり言語特性を理解したいなと思い、`golang`について調べてみた。

【参考にしたサイト】
・ [golang公式(FAQ)](https://golang.org/doc/faq#What_is_the_purpose_of_the_project)
・[Go言語らしさとは何か？を題材にした記事](https://employment.en-japan.com/engineerhub/entry/2018/06/19/110000)
・[golangの並列処理について理解しやすい記事](http://ascii.jp/elem/000/001/480/1480872/)

## golangが作られた背景
- 動的型付け言語のプログラミング容易性、静的型付け言語の安全性・効率的なコンパイルを一つの言語で享受したい。
- マルチコアプロセッサを生かした優れた非同期処理による実行効率を目指した。
- 本当に開発者が必要だと思う機能のみを提供するように、言語仕様をリッチにしないことにより、開発者の迷いを無くし、生産性の高い開発をサポートしたい。


## golangの強力な機能
### interface
- `golang`の`interface`は`interface`に定義したメソッドを実装しただけで`interface`を実装していると見なされる。
- これは`interface`を「ある概念を表すための振る舞いを定義するもの」としてではなく「概念を扱う側がどう扱いたいかを定義するもの」として扱えるということだと理解。
- 「依存性逆転の法則」を正確に、コンパクトに実現できるようになっている。

```golang:main.go
package main

import (
	"fmt"
	"strconv"
)

// メイン処理
func main() {
	PrintGame(Soccer{11, "サッカー", 120})
	PrintGame(Chess{9, "チェス", 9})
}

func PrintGame(g Game) {
	fmt.Println(g.getGameName() + "は" + strconv.Itoa(g.getPlayerMemberCount()) + "人で行うゲームです")
}

// ゲームインターフェース(メイン処理で使いたいもののみを定義)
type Game interface {
	getPlayerMemberCount() int
	getGameName() string
}

// サッカー構造体
type Soccer struct {
	playerMemberCount int
	gameName          string
	playTime          int
}

func (s Soccer) getPlayerMemberCount() int {
	return s.playerMemberCount
}

func (s Soccer) getGameName() string {
	return s.gameName
}

// チェス構造体
type Chess struct {
	playerMemberCount int
	gameName          string
	boardSize         int
}

func (c Chess) getPlayerMemberCount() int {
	return c.playerMemberCount
}

func (c Chess) getGameName() string {
	return c.gameName
}

func (c Chess) getBoardSize() int {
	return c.boardSize
}

```

### コンポジション
- 継承という概念を無くし、オブジェクト志向言語として扱いたい場合に、継承ではなく移譲を強制し、コードの複雑さを取り払う。
- 個人的には多重継承された実装は可読性が低く、スパゲティコードの温床になり得ると思っているので、この仕様は好み。

```golang:main.go
package main

import (
	"fmt"
	"time"
)

// メイン処理
func main() {
	order := Order{"パン", OrderDetail{100, "buy", time.Now()}}
	fmt.Println(order.getItemName())
	// 注文に埋め込んだ構造体のメソッドを直接呼び出せる
	fmt.Println(order.getOrderPrice())
	fmt.Println(order.getBuySellType())
	fmt.Println(order.getOrderDateTime())
}

// 注文構造体
type Order struct {
	itemName string
	// 注文明細を注文に埋め込み
	OrderDetail
}

func (o Order) getItemName() string {
	return o.itemName
}

// 注文明細構造体
type OrderDetail struct {
	orderPrice    int
	buySellType   string
	orderDateTime time.Time
}

func (d OrderDetail) getOrderPrice() int {
	return d.orderPrice
}

func (d OrderDetail) getBuySellType() string {
	return d.buySellType
}

func (d OrderDetail) getOrderDateTime() time.Time {
	return d.orderDateTime
}

```

### 非同期処理
`golang`には並行処理を行える機能として`goroutine`が実装されています。
`goroutine`は「並列処理」ではなく「並行処理」を行う機能です。(自分も曖昧だった概念のためこの機にちゃんと理解した。。)

`goroutine`が他の言語の並行処理に比べて優れていると言われている点は二つ。

- 並行処理の確保するメモリが軽量
- 並行処理の実行速度

この二点について調べてみました。

##### 並行処理の確保するメモリが軽量
一つの`goroutine`が起動時に確保するメモリ容量と、メモリ確保の方法に起因しています。
一般に、スレッドを複数起動して処理を行う場合、一つのスレッドを起動するにあたり、プロセス内のメモリ領域がスレッド同士で干渉し合わないように大きめにメモリ領域(1MBくらいらしい)を確保します。

それに比べて`goroutine`はスタック領域に2KBほどを確保するのみだそうです。そこから`goroutine` として動作する関数の必要とするメモリのみをヒープ領域に割り当てていく仕組みになっている。

そのため、何千何万とスレッドを立てるには膨大なメモリが必要になりますが、`goroutine`であればそんな心配はしなくて良いということ。だと思う。

##### 並行処理の実行速度
これはスレッドがコンテキストスイッチを行う時に比べて、`goroutine`の行うコンテキストスイッチの方がコストが少ないということに起因している。
スレッドであればCPUの複数のレジスタから複数のレジスタにスレッドの扱っているデータを退避させるという作業が発生しますが、`goroutine`であればせいぜい3,4種類のレジスタの退避を行えば良いだけなのです。

また、`goroutine`のスケジューラは`goroutine`のブロッキング処理を検知すると別の　`goroutine`の処理を実行し始めるため、システムリソースを無駄にしないよう設計されています。


## 最後に
ここまで`golang`の機能や設計思想について調べた結果を記載しましたが、調べる中で、かなりスリム化された言語であると感じました。
業務では`java`を使用していますが、色々便利な機能があったり、汎用的に実装するための機能が提供されています。
が、私を含め多くのメンバーが`java`のそういった機能を使いこなせているかというとそうではないと感じています。
それどころか、そういった機能を使うことにより保守しにくいコードを量産してしまっているのでは。。

そのため、`golang`のように面白みがない言語だと揶揄されることがあっても、保守しやすいコードを効率的に書くことをある程度強制するような言語に触れることは、学びになると思いました。
これからも`golang`を趣味ではありますが、書いていこうと思います。