Go言語への道　〜導入〜

# 目的

とある開発案件で、はじめてGo言語を使ったWebアプリケーションを開発することになりました！
なので、自分用の学習メモとして記録を残しておこうと思いこの記事を書いています。
また、同じシチュエーションでこれからGo言語を始める方の参考になれば幸いです。

# 開発環境

* macOS Catalina 10.15.4（19E287）
* go 1.14.2

# Go言語とは

2009年にGoogleが開発したオープンソースのプログラミング言語であり、Google社内におけるソフトウェア開発の生産性や拡張性のために開発されました。開発者は、UNIX開発に携わったロブ・パイク氏と、UNIX開発とC言語を開発したケン・トンプソン氏が設計しました。
対応OSは、Linux、MacOS X、Windows、Android、iOSとなっており主要なものはサポートされています。
ちなみに、正式名称は「Go」なのですが、それだけだと別の意味に捉えられることもあるので、「Golang」や「Go言語」と呼ばれることが多いようです。本記事では、「Go言語」と呼びます。

## Go言語の特徴

C言語を意識しながら設計されている言語で、C言語以上にシンプルかつ信頼性があり、無駄のない有能なソフトウェア開発を簡単に実現できます。ゆえに、実用性があり、効率よく作業を行うことが可能なため、軽量・高速・シンプルなプログラミング言語として知られています。

### 1.シンプルな言語構造

複雑な機能は削られており、とてもシンプルな言語構造になっています。例えば、プログラミング言語では繰り返し処理を行う時に、for文とwhile分の2つが準備されています。しかしGo言語の繰り返し処理はfor文しか存在していません。このように言語をシンプルにすることで、高速コンパイルの実現やミスの軽減に役立っています。

### 2.誰が書いたコードでも読みやすい

言語構造がシンプルであるため、だれが作っても殆ど同じになる様に設計されています。また、コーディング規約に沿ってソースコードを自動整形してくれる`go fmt`があり、これを利用すると見た目が整い非常に見やすくなります。また、記述ルールが厳格なので、記述に迷うことなく決まった書き方で開発が進められます。

### ３.実行速度が速い

直接ネイティブコード（機械語）に変換することにより、高速でコンパイルが可能となります。また、コードの種類がシンプルで限定的であるため、内部処理も簡易化され、同時に複数の処理を実行できる仕様になっていることからも、より軽量・高速での処理が可能です。

### ４.並列処理に強い

大量データ処理には並列処理が必要になりますが、Go言語は並列処理を得意としており、`goroutine`や`channel`などの機能を使うことでCPUへの負荷などを気にせずに処理を進められます。

### ５.拡張性（スケーラビリティ）が高い

Go言語では、小さな機能を必要に応じて組み合わせることで高い機能性を実現していくため、拡張性が高い言語と言えます。

### ６.クロスプラットフォーム対応

Go言語は、クロスコンパイルという、開発しているOSとは異なる環境向けに実行可能なコードを生成することが可能であるため、OSやソフトウェアが異なるシステム上でも実行できます。

### 7.消費リソースが少ない

リソースのコストパフォーマンスが非常に良いと言われています。例えば、同様の処理をJavaと比較した場合、メモリはJavaの約30分の1ですみます。

## Go言語のデメリット

### 1.Genericsがない

Go言語ではGenericsをサポートしていないため、Javaのgeneric typeのような記述はできません。これにより、安全性の高いメモリ管理やシンプルな構造を保っていると言えます。
Genericsは型を汎用化することができますが、適切に使用しないと逆にソースコードが乱雑になる危険性があります。それを避けるため、Go言語ではあえてGenericsをサポートしていないのです。

### 2.継承をサポートしない

コードの再利用や拡張性を高める上で役立つ「継承」もサポートされていません。少ないコードでプログラムできるというメリットはありますが、コードが複雑になれば継承により読みづらくなるという場合もあるからです。
規模の大きなシステム開発におけるコードの読みやすさや、メンテナンスのしやすさが優先されています。

### 3.例外処理がない

RubyやJavaの例外処理と同様の機能はありません。これも、Go言語がシンプルであることを保つために削ぎ落とされた機能です。
その代わり、`Panic`や`Recover`を使えば、エラーを処理する例外と近い機能が実装できます。

## Go言語でできること

Go言語がどのような用途で主に使われているのか、得意なのかについて、以下で紹介します。
以下のもの以外でも、AI開発でも徐々に需要を増やしており、多くのシェアを持っているPythonと並ぶ程の注目があり期待されています。

### Webサーバー/Web API構築

標準ライブラリのnet/httpパッケージを使用すれば、Webサーバー・Web APIを簡単に構築できます。
Go言語の特徴である、高速・軽量・並列処理に強い点などが生かされています。
代表的なものとして、YouTubeもGo言語で構築されています。

### アプリケーション開発

AndroidやiPhoneといったスマートフォンで動作するネイティブアプリケーションの開発も可能です。モバイル向けのアプリ制作に使うツールが集められた`Go mobile`を使えば、開発がとても快適に行えます。

### コマンドラインインターフェース（CLI）ツール作成

コマンドベースで操作を行うCLIによって動作するアプリケーション制作にもGo言語は向いています。
Go言語はマルチプラットフォームに対応したクロスコンパイルの機能があるので、それぞれのプロットフォーム による互換性や依存関係を心配せずに、環境に適したツールの制作が簡単に行えます。

# Go言語のインストール

ちょっと座学が長くなってしまいましたね。
それでは、まずMacにGo言語をインストールしてみましょう。
事前準備として、Macに[Homebrew](https://brew.sh/index_ja)をインストールしておいてください。

### インストール
```
$ brew install go

Updating Homebrew...
==> Downloading https://homebrew.bintray.com/bottles/go-1.14.2_1.catalina.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/15/15b5623471330edcc681d7f9d57b449660e6d4b98c7f67af67f4991fc75d61fc?__gda__=exp=1589359948~hmac=bf89e2d60937f105e542c1b210786b7ef609ac57c7934ddd5f4a03f9f7749682&response-content-disposit
######################################################################## 100.0%
==> Pouring go-1.14.2_1.catalina.bottle.tar.gz
🍺  /usr/local/Cellar/go/1.14.2_1: 9,440 files, 424.4MB
```

### バージョン確認
```
$ go version

go version go1.14.2 darwin/amd64
```

これでインストールは完了です。
2020年5月現在の最新バージョンは1.14.2です。

# Go言語でHello World！

それでは実際にプログラムを動かしてみましょう！！

```
# ディレクトリ作成
$ mkdir -p ~/golang/example

# 移動
$ cd ~/golang/example

# テストプログラムを作成
$ vi hello.go
```

`hello.go`の中身は以下のように記述します。

```hello.go
package main

import "fmt"

func main() {
    fmt.Printf("Hello, World\n")
}
```

それでは実行です。

```
$ go run hello.go

Hello, World
```

ビルドもしてみましょう。

```
$ go build hello.go
$ ls
hello		hello.go
$ ./hello
Hello, World
```

ビルドするとプログラムファイルと同じディレクトリに`hello`というバイナリファイルができました！
これを実行すると、`go run`と同じ結果が返ってきますね。

ちなみに、`go run`と`go build`の違いはなんでしょうか。。。

`go run`は、自動的にコンパイル・実行を同時に行ってくれるコマンドですね。簡単なテストなどで有効ですね。
ただし、カレントディレクトリ以下の全ファイルを読み込むわけではないので、importされたパッケージのみ読み込み、同階層のmainパッケージに属する別関数などは無視されてしまうので注意が必要です。

`go build`は、自動的にmainパッケージを読み込み、main関数があるファイルを特定し、そのファイル名を使ったバイナリファイルを生成します。
基本的にはカレントディレクトリ以下をスコープにして読み込んでコンパイルするファイルを決めるので、カレントディレクトリ以下にあるファイルが読み込まれないといったことはありません。
ビルド時に色々とオプションなどがあるみたいなので、そのあたりままた別途学習してみようと思います。

### ちなみに、、、

下記のように、main関数の括弧を別の行に書くと"syntax error"になってしまいました。
結構、がちがちにコーディング規約が決まっているのね。。。

```hello.go
package main

import "fmt"

func main()
{
    fmt.Printf("Hello, World\n")
}
```

```
$ go run hello.go

# command-line-arguments
./hello.go:5:6: missing function body
./hello.go:6:1: syntax error: unexpected semicolon or newline before {
```


また、Go言語には標準でコードを整形（静的解析）してくれる機能`gofmt`があるようです。
下記のようなコードを`gofmt`にかけてみます。

```(整形前)hello.go
package main
import "fmt"
func main(){
fmt.Printf("Hello, World\n")
}
```
```
$ gofmt -w hello.go
```
```(整形後)hello.go
package main

import "fmt"

func main() {
	fmt.Printf("Hello, World\n")
}
```

空行・インデントが追加されました！！
これを使えば、複数のエンジニアで記述したコードもある程度統一できそうですね。

# まとめ

ここまでで、Go言語の基礎知識、インストール方法、実行まで学習してきました。
まだ、曖昧な部分が多くてフワフワしていますが、徐々に知識を深めていければと思います。
次回は、Go言語の[公式ドキュメント](https://golang.org/doc/effective_go.html)をもとに、基本構文を学習してみようと思います。

ども、ありがとうございました。