Go言語を試す

## 環境設定

* Go言語仕様
https://golang.org/ref/spec

* goのインストール
https://golang.org/

* go getでパッケージを取れるか
https://pkg.go.dev/
go get xxxx

* Goland
有料のIDE

* VSCode
cmd + j でVSCodeのパネル開く
go run xxxx.go で実行
go build xxxx.go でバイナリファイルが残る

* delve デバッガ
go get github.com/go-delve/delve/cmd/dlv
launch.jsonを作成 -> vscodeのrunタブにボタンが有る

## 基本 

* main.goから始まる
* init() 関数は強制的に最初に実行される
* 使わない変数を書くとコンパイルできない
* 先頭は大文字でパブリック、小文字だとプライベートになる
* fmt.Println()で出力

### import
標準パッケージ一覧
https://golang.org/pkg/
パッケージはimportして使う
パッケージとはコードの集まり。ライブラリもほぼ同じ意味。クラスはない。
ディレクトリ名がpackage名となる。その中にgoファイルを配置。

```
app
L main.go
L package1
  L file1.go
  L file2.go
L package2
```

### 変数
var i int = 3
float64, string, bool
var を () でくくればvarを毎回先頭に付ける必要はない
初期値を代入しなかった場合デフォルト値となる。0、空文字、falseなど
fmt.Printf("%T\n", xi)

### short variable declaration
xi := 1
xs := "ccc"
代入により自動で型が決まる
関数内でしか使えない

### const
書き換えられない
型がない(untype)（実行するまで解釈されない）
通常はグローバルに書く
通常は先頭は大文字

### 数値
言語仕様
https://golang.org/ref/spec#Numeric_types

i++ 対応

### 文字列
インデックス指定でアスキーコード取得、stringで文字に変換
string("Hello"[0])
文字の置き換え
var s string = "Namaste"
s = strings.Replace(s, "N", "Z", -1)
strings.Contains(s, "mas")
バッククオートでヒアドキュメント ``

### 論理値
変わったところはない
&& || !

### 型変換
int float64
文字 -> 数字はpythonみたいにstringではできない
i, _ := strconv.Atoiで変換

戻り値をアンダースコア(_)で受け取れば、未使用でもコンパイルできる

### 配列
型部分で宣言したサイズは変更できません
var b [2]int = [2]int{30, 40}

### スライス
サイズ変更できる配列
var b []int = []int{30, 40}
b = append(b, 50) で追加

var n []int 初期化しないとnilになる
n := make([]int, 0) だと中身は空だがメモリ上に存在する

### map
m := map[string]int{"apple": 100, "banana": 300}
新しいキーに代入すると追加される

var m map[string]int 初期化しないとnil mapになり、追加できない

m := make(map[string]int) はnilじゃない
a, ok := m["grape"]
keyが存在しないと0を返し、2つ目の返り値にfalseが返る

### バイト
b := []byte{72,73}
stringで文字列にキャストできる
c := []byte("HI")
文字列を渡すとアスキーコードに変換される

アスキーコード変換表
https://www.ascii-code.com/

### 関数
引数の型が同じ場合はまとめられる
返り値が複数の場合は()でくくる

```
func add2(x, y int) (int, int) {
	return x + y, x - y
}
```

### 名前付きの戻り値 Named Return Values 

```
func calc(price, item int) (result int) {
  result = price * item
}
```

返り値として宣言した名前を変数として扱えるので、returnを書く必要なし
返り値が多くなってわかりにくい時など

### Inner Function 
関数内で変数に関数を代入して使う

```
f := func()
```

名前無し関数も作れる

```
func(x int) {
}()
```

### クロージャー closure
関数を返す関数

```
func increment() func() int {
```

関数を戻す前に投入したパラメータを、戻した関数の処理に引き継ぐ事ができる

```
func circle(pi float64) func(radius float64) float64 {
	return func(radius float64) float64 {
		return pi * radius * radius
	}
}
```

### 可変長引数 Variadic Function Parameter
任意の個数の引数を受け取れる

```
func foo(params ...int) {
```
関数の中ではスライスで受け取れる

スライスを可変長引数の関数に渡すには

```
// スライスが展開される
foo(s...)　
```

### コードスタイル
イコールの位置をそろえるのがgoの慣習
列挙する場合は演算子は詰めて書く 

```
var a    = 100
var bbbb = 200
var cc   = 300

fmt.Println(1+1, 2*2)
```

##ステートメント
### if
()はなくて良い
;で一文でかける

```
// if / else if / else
if result == "ok" {
```

### for
```
continue
break
//初期化とインクリメントを省略できる ;も省略できる
for sum < 10 { 
} 
```
for { } だけだと無限ループできる

### range
リストやマップをかんたんに表示できる

```
for i, v := range list {
```
インデックスを使わない場合は _ で置き換える
マップのバリューのみ使わない場合は書かない
マップのキーのみ使わない場合は _ で置き換える

### switch
switchの判定のみ使うのなら、;の前で取得して一文でかける
変数を書かなくても分岐に使える 

```
switch {}
```

### defer
前につけることで関数が終わったあとに実行する指示
close処理忘れ防止など

```
func defaTest() {
	defer fmt.Println("defer") // 関数が終わったら実行されます
	fmt.Println("end")   
}
```
deferはスタッキングされるので、複数あると最後から表示される


### log
go logging package 

```
log.Println()
log.Fatalln() // Fatalはそこでプログラムが終了する
log.SetOutput //設定
```

### エラー
goは戻り値のerrを使って処理する（トライキャッチじゃなく）
:= はどれか一つを初期化してたらエラーにならないが一つもなければアウト

```
count, err := file.Read(data) 
```

### panic、recover
deferでrecover()してpanic()が起きても正常終了させる
recoverはpanicの前に書く
基本panicをあえて書くのではなく、エラーハンドリングをするべき

## ポインタ

### ポインタ
```
var p *int = &n //intのポインタ型、アドレスを格納
p //アドレス
*p //ポインタが指す値
```

### new make
指定の型のメモリ確保する

```
var p *int = new(int)
```
*p は0になる
スライスやマップはmakeでメモリ確保(ポインタを返さない)

### struct 構造体
先頭は大文字でパブリック、小文字だとプライベートになる

```
type Vertex struct {
	X int
	Y int
	S string
}
v := Vertex{X: 1, Y: 2}
```

初期化しなければデフォルトが入る
名前を指定しなければ順番どおりはいる

アドレスを取る場合、newよりも&を先頭につける事が多い
（マップやスライスなどはmakeを使うほうが多い）

structの場合は、参照渡しでも*つけずに値にアクセスできる！！

## struct
### メソッド
定義済みstructに関連付けてドットで呼び出せる関数（値レシーバ）

```
func (v Vertex) Area() int {
```

structを参照渡しして、メソッド内で中身を書き換えるもの（ポインタレシーバ）

```
func (v *Vertex) Scale(i int) {
```

### コンストラクタ
structをプライベートにすると他のパッケージからアクセスできないので
Newメソッドで初期化する

```
func New(x, y int) *Vertex {
	return &Vertex{x, y}
}
```

packageName.Newすることでstructを返す

### embeded
structの中にstructを定義すると、クラス継承みたいな感じで拡張できる

```
type Vertex3D struct {
	Vertex //名前を書くだけ
	z int
}

func New(x, y, z int) *Vertex3D {
	return &Vertex3D{Vertex{x, y}, z}
}
```

### non-struct
structではないカスタム型もメソッドをつけられる

```
type MyInt int
func (i MyInt) Double() int {
```

### interface
メソッド名だけ書かれている型
structがメソッドを実装してないとエラーになる

```
type Human interface {
	Say()
}
```

使うにはstructを作るときに変数の後ろにつける

```
var mike Human = Person{"Mike"}
```

引数をinterfaceで宣言して、メソッドを実装済みのstructのみ受け付けるようにできる（ダックタイピング）

### タイプアサーション
引数の型を interface{} にすれば何でも渡せる
その場合、i.(int) などで型を変換することをタイプアサーションという
インターフェースでない通常の型の変換（タイプコンバージョン、キャスト）とは違う

switch type文で複数の型に対応

### Stringer
string()メソッドを実装するとそれが標準出力になる

```
func (p Person2) String() string {
```

### カスタムエラー
自分なりのエラーを出したい場合はString()同様、Error()を実装すればよい

```
func (e *UserNotFound) Error() string {
```
Error()はポインタ型推奨

エラーを比較するときはポインタで比較しないと同じエラーになっちゃう

## まとめ
C言語みたいだと感じた

## 参考
[現役シリコンバレーエンジニアが教えるGo入門 + 応用でビットコインのシストレFintechアプリの開発](https://www.udemy.com/course/go-fintech/)