Golang勉強メモ　雑記

golangを動かして思ったことを雑多にメモする
大きくなりそうなものは別途記事としてまとめる

# 静的解析が便利（らしい）
### 静的解析とは
コードを実行せずにきれいにしてくれるマン
golang自体がシンプルなコードで、静的解析のしやすさを目指しているらしく
静的解析との相性がいいらしい。
https://golang.org/doc/faq#change_from_c
>Second, the language has been designed to be easy to analyze and can be parsed without a symbol table. 

### fmt
公式から提供されているフォーマッタ。
ファイル保存のタイミングで、自動的にソースのフォーマットを行ってくれる。
実施してくれるのは

* 行間のフォーマット
* 変数、型のインデント揃え
* 不要（ソース内未使用）パッケージの削除
* 制御構文の()削除※
※golangはif,switch,forの制御構文に()は利用しない


など
![ezgif-3-89c5e65aac7a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298390/b0f49f43-6747-ea22-99a7-6b5d7ef72dad.gif)

fmtやgoのフォーマットに関する詳しい情報はこちら
[Command gofmt](https://golang.org/cmd/gofmt/)
[Effective Go](https://golang.org/doc/effective_go.html#formatting)

使おうと思っている自作のパッケージをimportに書いて、
コード内で使用せずに保存すると消えてしまうのでちょっと悲しい。

### lint 
コードの改良案を提案してくれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298390/705c2184-660e-1de4-33a1-49f18e765766.png)
おおまかな提案内容は以下の通り

* 構造体へのコメント付与
* パブリック関数へのコメント付与

### vet
デッドコードの検出をしてくれる。
デフォルトじゃ入っていない気がする。
未着手。



# packageの扱い
とりあえず色々ソースを作って動かそうと思ってこんなディレクトリ構成にしてる。
`gogo.go`は疎通確認、`person.go`は構造体のテストで
お互い独立したソースファイルである。

```
golang
├gogo.go
└person.go
```

goは

* 少なくとも1つの`package`に所属する必要がある
* コンパイル→実行時に`package main`の`main`関数を実行する

ので上記両ファイルともpackage mainに所属させ、main関数を作成すると
修飾子が重複していると注意されてしまう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298390/a7658ea3-ccdc-848c-41b6-1eeee242c9e0.png)

`go run person.go`のようにファイル名を指定して実行すると
一応実行はできるのだが、ちょっと気持ちわるい。
パッケージへの所属が必須の言語ではどう整理するのが正解なのか。

一旦は作りたいソースごとにパッケージにわけ、
main.goでソースを呼び出す形に変更することに。

```
golang
├main.go
├hello
│└gogo.go
└person
 └person.go
```


```
package main
import "./person"
import "fmt"

func main() {
	fmt.Println("start")
	person.score()
	
}
```



```
package person

import (
	"fmt"
)

// Person はテストの点数管理の構造体です。
type Person struct {
	name    string
	english int
}

func score() {
	bob := Person{"Bob", 60}
	fmt.Println(bob.name, bob.english)

	if bob.english > 60 {
		fmt.Println("OK")
	} else {
		fmt.Println("NG")
	}
}
```

これで`main.go`から自作の`package person`を読み込めると思ったのだが、
参照できず、import文から削除される・・・


原因を調査したところ、golangでは
メソッド名が小文字の場合、package外に非公開(private)、
メソッド名が大文字の場合、package外に公開(public)という設定になるらしい。
[公式ドキュメントだとこのあたり？](https://golang.org/doc/effective_go.html#Getters)
>If you have a field called owner (lower case, unexported), the getter method should be called Owner (upper case, exported), not GetOwner. The use of upper-case names for export provides the hook to discriminate the field from the method. 

下記の通りメソッド名を大文字にしたところ実行できた。
小文字でも自コード内での参照はできるため、エラーにならず
原因解明に時間がかかった。

```
package main

import (
	"fmt"

	"./person"
)

func main() {
	fmt.Println("start")
	person.Score()

}
```

```

package person

import (
	"fmt"
)

// Person はテストの点数管理の構造体です。
type Person struct {
	name    string
	english int
}

// Score 評価のためのメソッド
func Score() {
	bob := Person{"Bob", 60}
	fmt.Println(bob.name, bob.english)

	if bob.english > 60 {
		fmt.Println("OK")
	} else {
		fmt.Println("NG")
	}
}

```

```
go run main.go
start
Bob 60
NG
```

# 参考ドキュメント
* [golang公式](https://golang.org/)
* [Go Codereview Comments（日本語訳）](https://knsh14.github.io/translations/go-codereview-comments/)