プログラミング経験者へのGo入門

## 対象者
Goやりたいですってなった時
「そうだ！ [Go Tour](https://go-tour-jp.appspot.com/welcome/1)やろう！」
となる人はGo Tourやってください。

他の言語でプログラミングしたことあって、Go気になってるって人向けです。

## 環境
- Mac
- Go1.18

## 下準備


```
go mod init github.com/yourname/example
```

## パッケージの作成

パッケージは他の言語でいうモジュールです。

今回は2x2行列を実装します。
2x2行列は4つの整数を持ち、積を計算する `Multiple` メソッドを持つものとします。

```
mkdir matrix
vim matrix/matrix.go
```

```go
package matrix

type (
	Matrix2D struct {
		// a, b
		// c, d
		a, b, c, d int
	}
)

func New(a, b, c, d int) Matrix2D {
	return Matrix2D{a, b, c, d}
}

func (m Matrix2D) Multiple(n Matrix2D) Matrix2D {
	a := m.a*n.a + m.b*n.c
	b := m.a*n.b + m.b*n.d
	c := m.c*n.a + m.d*n.c
	d := m.c*n.b + m.d*n.d
	return New(a, b, c, d)
}
```

Goにはクラスはありません。
代わりに構造体を `struct` キーワードで定義します
構造体のMatrix2Dは a,b,c,d の4つのintをプロパティとして持ちます。
Goではメソッドは構造体定義と別で書きます。
上記のコードで `Mutltiple` メソッドはMatrix2Dのメソッドとして定義されます。

`func (m Matrix2D) Multiple` みたいに `func` キーワードとメソッド名の間に `(m Matrix2D)` という記述をすることで
構造体のメソッドとして定義されます。

この `m` はなんでも良いです。 `(matrix Matirix2D)` など。
メソッド内で自身の構造体を参照する時に使われるのがここで記述した `m` です。
他の言語では `self` や `this` みたいに予約語とされていますが、Goではエンジニアが自分で名前を定義します。
これをレシーバー引数と言います。


最後に `New` 関数を見てみましょう。
これはレシーバー引数が定義されていないので、構造体のメソッドではありません。
これはmatrixパッケージに定義された関数です。
これをどうやって呼び出すかは後述します。

### Goコードの大文字小文字について
Goでは先頭が大文字ならパブリック、小文字ならプライベートとなります。
プライベートなものは同じパッケージないからしかアクセスできません。

```
package matrix

var (
  PublicVar int
  privateVar int
)

func PublicFuncName() string { return privateFuncName() } // パッケージ内ではprivateFuncNameを呼び出せる。
func privateFuncName() string { return "080-XXXX-OOOO" }
```

### ファイルとパッケージについて

matrixディレクトリに二つのファイルがあるとします。
```
/matrix / matrix.go
        / determinant.go
```

同一パッケージ内のものは別ファイルからも参照できます。

```matrix.go
package matrix

var (
  hello string // プライベート変数。
)

type Matrix2D struct { a,b,c,d int }
```


```determinant.go
package matrix

import "fmt"

// ファイルdeterminant.go内では Matrix2D構造体は定義されていないが、型を参照できる。
func (m Martrix2D) determinant() int {
    fmt.Println(hello) // hello変数はファイルdeterminant.go内では定義されていないが参照できる。
    // Snip...
}
```


## パッケージを使用する。

ディレクトリ構成
```
main.go
matirx / matrix.go
       / determinant.go
```

main.goを作成して、matrixパッケージのコードを呼び出します。

```main.go
package main

import (
    "fmt"

    "github.com/yourname/example/matrix"
)

func main() {
    m := matrix.New(1,2,3,4)
    n := matrix.New(2,4,6,8)
    fmt.Prtinln(m.Multiple(m))
}
```

`import` に依存するパッケージを追加します。
インポートしたパッケージはパッケージ名で参照できます。
matrixパッケージに定義したNew関数を呼び出すにはパッケージ名にドットをつけて呼び出します。

`matrix.New(...)`

関数の他に、型定義や変数も同様に参照できます

```go
matrix.Matrix2D{}
matrix.PublicVar
```

ちなみに構造体を生成するときは中括弧を使用します。
ただし、今回のコードでは構造体のフィールドは a,b,c,d と小文字で定義されています。
これはプライベートを意味するのでパッケージ外から直接初期値をセットできません。
```
matrix.Matrix2D{}
```


---
ちなみに
インポート時に参照する名前を変更することもできます。
この時以下のように参照名を変更できます。
```go
import (
    myMatrix "github.com/yourname/example/matrix"
)
func main() {
    myMatrix.New(1,3,3,4)
}
```


## 実行
```
go run main.go
```

## GitHubに公開されているパッケージを使う

以下のように import 内に使用したいパッケージを指定します。
その後 `go mod tidy` を実行するだけです。
**注意** Go1.18を使用しています。古いGoではやり方が異なります。

```go
// Snip...

import (
    "golang.org/x/example/stringutil"
)
```

あとは同様にパッケージ名で参照します。

```go
func main {
    fmt.Println(stringutil.Reverse("olleH")) // Hello
}
```

## まとめ
- パッケージの作成方法
- 構造体とそのメソッドの定義方法
- プライベート、パブリックについて
- パッケージの使用方法

あたりがわかったと思います。

最初にGoを触ると小文字がプライベートということによく引っ掛かります。
練習のうちは思考停止でアッパーキャメルケースを使用することをおすすめします。