Go言語初学者が勉強する過程で収集した情報まとめ

# Go言語を習得する過程で自分で学んだこと・参考情報サイトなどをまとめていきます
すなわち本内容は完成記事ではなく学習の過程で記事を加筆していくつもりです。
割と個人の覚書きの性質の強い記事ではありますが、ひょっとしたら他の「これからGoをやるぞ！」と思う人の助けになることがあるかもしれないので公開します。
各セクションについて、ボリュームが膨らんできてここに載せておくには文章量が多いな…と感じてきたらその部分は単独記事として独立化させていく予定です。

## 基礎：まずはこのあたりから勉強

### プログラミング言語Go完全入門
https://docs.google.com/presentation/d/1RVx8oeIMAWxbB7ZP2IcgZXnbZokjCmTUca-AbIpORGk/edit#slide=id.g4f417182ce_0_0

このドキュメントは、仕様を言葉で定義してくれないので、サンプルを見て「わかれ」という書き方なので個人的にはあまり好みじゃないのですが、公開時期が2019年と比較的新しく、これが分かりやすいとおススメしている方もいるので紹介します。質問ができるコミュニティへの案内があるのはありがたいですね。

### 公式ドキュメント

https://go.dev/ref/spec

公式ドキュメントの言語仕様のページは英語かつ書き方が人間に優しくない形式文法っぽい感じなので読むのがめんどい…。まあ厳密に正確な定義をすべき公式ドキュメントだから「この仕様どうなってたっけ？の最終的な答え合わせ」がしたい時にはこれを参照するのがいいんでしょうね。（ただ、初心者が一番最初に読むものではないと思う）

https://go.dev/tour/list

Tour of Go は色んな人にオススメされるのでやっておいたほうがよさそう？（まだ筆者はあまり進められていないので、進めたら感想を追記します）

### はじめてのGo

https://gihyo.jp/dev/feature/01/go_4beginners

このドキュメントが個人的に好み(日本語で読める。ある程度厳密な仕様がわかる)。デメリットは執筆時期が2015年とちょっと古めなことか。Goは割と活発にバージョンアップしている言語みたいなのでちょっと前の古いテキストだと最新仕様とズレが大きくなるのが心配かも。

→　(2023/02/11追記)GOPATH使う前提でgo modが標準になる以前の教え方なのでこれを読みながらGoの勉強をするのは現在ちょっと辛くなってきた…別の資料をあたるほうが良さそう…

### Go言語の初心者が見ると幸せになれる場所

https://qiita.com/tenntenn/items/0e33a4959250d1a55045

勉強が軌道に乗り出したあたりで、より実践的な情報、好ましい書き方を身につけるために読むとよさそう

### Go強化月間～開発する上で知っておくべき知見を共有しよう～
https://qiita.com/official-events/ae80b010f51f7018891a

### Goを学ぶときにつまずきやすいポイントFAQ 

https://future-architect.github.io/articles/20190713/

Go言語特有のクセについて説明してくれている。一度目を通しておいたほうが良さげ

### 「Go初心者が気を付けること」の解説

https://zenn.dev/nobonobo/articles/e0af4e8afc6c38b42ae1

初心者がハマりやすいポイント、他言語では適切だがGoでは不適切なコーディングなどが書かれている

### Go言語は沼

https://qiita.com/yasuo-ozu/items/3eb4a6c0180baa3bd851

こちらも初心者がハマりやすいポイントが列挙されています

https://qiita.com/mumoshu/items/0d2f2a13c6e9fc8da2a4

新規プロジェクトの作り方などが載っています

## 実行環境

### MacでGoをインストールする場合
MacでHomebrewからgoをインストールした場合、.zshrcにはどう設定すべきか、どこにPATHを通すべきかなど、分からなくなった時はこの記事参照。
↓

https://zenn.dev/y16ra/articles/251c3770365689

`go install`でインストールしたバイナリや、自分で`go build`した時のバイナリが保存される場所である`GOPATH`はOSで上書きすることもできるが、デフォルトで`~/go`が設定されているから変える必要がなければ特に設定不要。
GOROOTも同様の理由で特に設定不要。

```sh
# GOの環境変数確認方法
$ go env GOPATH
=> /Users/USERNAME/go

$ go env GOROOT
=> (goがインストールされている場所)
```

↓

https://zenn.dev/creamstew/articles/20e7a00c2eb161edbb1e

PATHはhomebrewでインストールしただけだと自動で設定されないようなので
GOPATHに置かれるバイナリをコマンドラインで実行したければ、PATHを通す必要がある

その場合は、`~/.zshrc`に下記の通り記載
```
# .zshrc
export PATH=$PATH:$(go env GOPATH)/bin
```

### 古いコードを動かしたい場合

https://zenn.dev/catatsuy/articles/fda1e42acad421

→　バグ原因調査で、ソフトの過去バージョンの動作を確認したいことがよくあるので、この記事が参考になりそう

### その他実行環境関係の記事
https://maku77.github.io/p/s258beh/

https://qiita.com/chano2/items/ea76cc503e651f07bfb0

### コンパイルや実行の手順
```sh
# main.go をコンパイルする
go build main.go
# コンパイルの結果作られた実行ファイル(バイナリ)を実行すればプログラムが起動する
./main
# 実行ファイル名を指定することもできる
go build -o build-name main.go
# -> ./build-name という実行ファイルが出来る

# コンパイルから実行までを一つのコマンド'run'で実行することもできる
go run main.go
```

もっと詳しく知りたい場合は公式ドキュメントを参照

`go build`

https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies

`go run`

https://pkg.go.dev/cmd/go#hdr-Compile_and_run_Go_program


### 環境変数GOPATHとは
-> インストールしたGoのバイナリや、外部のパッケージを配置するためのディレクトリ。GOPATH通した場所においたパッケージはimport可能になる

```shell
# GOPATHの値確認
printenv GOPATH

# GOPATHの場所へ移動
cd $GOPATH

# GOPATH直下のディレクトリ構成
ls $GOPATH
# -> bin pkg
```

https://go.dev/play/

↑ ブラウザで動く実行環境。さっと動作確認するのにオススメ。

## モジュールとかパッケージとか

公式ドキュメントではこの辺り

https://go.dev/ref/mod
> A module is a collection of packages that are released, versioned, and distributed together.
>
> 引用元: https://go.dev/ref/mod

「モジュールとは、一緒にリリースされ、バージョン管理され、配布されるパッケージの集まりである」と書かれているので、包含関係としては「あるモジュールには、１個以上のパッケージが含まれる」ということになる。

最近のGoでは、`go mod`を使うやり方が標準になっており、それ以前の`GOPATH`を使うやり方で教えている文献は参考にしないほうがいいかも…（もしくは、そのギャップを脳内で補正できるようになってから読むべき）

https://blog.framinal.life/entry/2021/04/11/013819

ここを読むと、モジュールの仕組みはなんとなく分かってきた。
上記ページを参考にするときの注意点として

> コマンドの意味 > 試してみよう

で、`go get`を実行する前に`hello.go`と同一ディレクトリで
```shell
go mod init hoge
```
を実行して go.mod を作成しておかないとその後の指示に従っても記事通りにコードが動作しない。
※ `go get`しても`go.mod`は作られないためである
※ が、GOPATHにgo-cmpのパッケージが追加されているのでimport は有効になっているし、go run すると実行はできる
※ IDEは`hello.go`において`could not import github.com/google/go-cmp/cmp`というエラーを吐いていた

https://zenn.dev/optimisuke/articles/105feac3f8e726830f8c

### go get と go install 

https://qiita.com/eihigh/items/9fe52804610a8c4b7e41

https://maku77.github.io/p/s258beh/



### その他パッケージ、モジュールについての各種解説（整理中)

https://qiita.com/fetaro/items/31b02b940ce9ec579baf

https://yrhw0609.hatenablog.com/entry/2020/10/17/230850

https://zenn.dev/nobonobo/articles/1d4afb9f4e8873

https://zenn.dev/nobonobo/articles/4fb018a24f9ee9


## 基礎文法

### データ構造

#### interface

型変換についても触れられた資料

https://qiita.com/sh-tatsuno/items/0c32c01eaeaf2d726fdf

#### 構造体

##### 初期化

https://qiita.com/cotrpepe/items/b8e7f70f27813a846431#%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E5%90%8D%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88

##### タグでメタ情報を構造体フィールドに付与

https://java-learner.tokyo/2021/03/23/go%E8%A8%80%E8%AA%9E-%E3%82%BF%E3%82%B0%E3%81%AE%E8%A8%98%E6%B3%95%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/

#### 配列

#### データ構造の操作

##### ループ(range)
https://go-tour-jp.appspot.com/moretypes/16

#### 日付・時刻型

https://qiita.com/tez/items/1fdcbd9e2b6b575b6725

https://qiita.com/ayasuda/items/39c6403fa855e4f9870b

https://blog.70-10.net/2018/07/31/go-time-parse/

### 関数

後日記載予定

### 型アサーション

```
<変数>が<型>であるかどうかをチェックする
value, ok := <変数>.(<型>)
```

https://blog.y-yuki.net/entry/2017/05/08/000000

##  ライブラリ

### [Echo](https://echo.labstack.com/)
Webフレームワーク 
WebAPIが作れる

### Gorm

[公式ドキュメント](https://v1.gorm.io/docs/)
[公式ドキュメント(日)](https://v1.gorm.io/ja_JP/docs/index.html)
ORマッパー

簡単に言うとGoでDBのデータ読み書きをするコードを書くためのライブラリ。
クエリを発行するには↓みたいな書き方をする

https://v1.gorm.io/ja_JP/docs/query.html#%E3%82%AF%E3%82%A8%E3%83%AA

#### GormでSQLインジェクションの脆弱性を回避するための注意

https://tech.andpad.co.jp/entry/2022/02/18/140000

↑　後で読む

### [Wire](https://github.com/google/wire)  

DI(Dependency Injection)：依存性の注入をするためのライブラリ

https://qiita.com/kez/items/657da2b8b643b69a2e21

https://www.asobou.co.jp/blog/web/google-wire

上記ページを参考に学習する際の注意

> フローを把握する > DI用の関数を生成する

の手順をそのまま実行すると`wire`コマンド実行したら
```
could not import github.com/google/wire (invalid package name: "")
```
というエラーが発生した

この場合、`wire`を実行する前に下記の方法でgo.modを作成しておく

```shell
$ go mod init hello
$ go mod tidy
$ cat go.mod
module hello

go 1.17

require github.com/google/wire v0.5.0
```
こうすると(ローカルに?)wireがインストールされるので
コマンド`wire`が実行可能になる

## テスト

### Go の標準テストパッケージ testing の使い方

https://pkg.go.dev/testing

- テストコードは {{hoge}}_test.go というファイル名にする
- テスト関数は Test{{Fuga}} という名前にし、`t *testing.T`という唯一つの引数をとる

#### テスト作成方法
下記記事でテストの自動生成について記載されています

https://zenn.dev/shunpay/articles/839b2805d6fd11


#### テスト実行方法

```shell
go test
# → {{hoge}}_test.go ファイルが存在するディレクトリで`go test`を実行する(引数不要)だけでテストが実行される

go test -run Piyo
# → Piyoという名前を含むテスト関数が実行される (例: TestPiyoFuga())

go test -run ^TestPiyo$
# → Piyoという名前に完全一致するテスト関数が実行される（例：TestPiyo()は実行される。TestPiyoPiyo()は実行されない)

go test -v
# → テスト内でPrintlnした時にデフォルトでは標準出力に出ないが、-vをつけると出てくるようになる
```

https://andmorefine.gitbook.io/learn-go-with-tests/

https://qiita.com/saya713y/items/f7ee07e8f12ab85ed9bf

https://future-architect.github.io/articles/20200601/

```
go test -count=1 
# テスト結果がキャッシュされなくなる
```
なぜこれでキャッシュされなくなるのか、詳しくはこちら↓

https://tech.yyh-gl.dev/blog/go-test-cache-clear/

## メモ・未分類

https://zenn.dev/myonyomu/scraps/62ad7dc059fc22

### 静的解析
https://www.slideshare.net/takuyaueda967/go-72025298

### 他言語との違いで戸惑ったこと
https://twitter.com/k_nulluo/status/1507712029469028357

↑ f文で初期化式を入れられるとか、関数の多値返却とか、今までの言語で自分がみたことのなかったような書き方に戸惑った話
なお、X.(T) は型アサーションである

https://zenn.dev/shinkano/articles/4779726fb964d9

### UberのGoプログラミングコーディング規約
https://github.com/knsh14/uber-style-guide-ja/blob/master/guide.md

### 例外処理

https://mattn.kaoriya.net/software/lang/go/20140416212413.htm

https://techdo.mediado.jp/entry/2019/02/15/120257

↑ 今読んでる