Golangをやっていて気になったことのメモ


### ■intのサイズはアーキテクチャによる

```go
// intのサイズはアーキテクチャによる
fmt.Println(32 << (^uint(0) >> 63)) // 64と出たら64bit
```

固定したい場合は、素直に `int32` と書く。

### ■型について

- 基本型（Bool, String, すべての数値）
- 合成型（Struct, Array）
- 参照型（Chan, Func, Ptr, Slice, Map, Interface{}）
- その他（reflect.Valueのゼロ値, 全く値ではないという意味の Invalid）

変数を入れ替えたり関数に渡す場合、コピーとなるため、structなどはポインタ型にしてから渡したほうが良い。

十分に小さいstructの場合は、デリファレンス（ポインタ解除）のほうがコストが高くなるため、ポインタ型にしないほうが良いらしいが、いちいち考えるのが面倒なため一律ポインタ型のほうが良いのかな？

参照型は生まれながらにポインタ型っぽい扱いなので、参照型に対してポインタ型を使う必要は無い。

### Golangの配列型Array型とSlice型について

Arrayが合成型なのがやばい。配列は基本Sliceを使っていったほうが良さそう。

```go
a := [3]int64{1, 2, 3} // array
s :=  []int64{1, 2, 3} // slice
```

※下記記事が詳しい
[Goのarrayとsliceを理解するときがきた](https://qiita.com/seihmd/items/d9bc98a4f4f606ecaef7)

### ■mapのキー存在チェックは、下記のように書くと速い

```go
map1 := map[string]string{"aaa": "aaa111"}
if v, ok := map1["aaa"]; ok {
  fmt.Println(v) // pring aaa111
}
```

### ■interface{}からキャストするときにもokがある

```go
func main() {
	type Foo struct {
	}
	var e interface{}
	e = Foo{}
	if _, ok := e.(Foo); ok {
		fmt.Println(e)
	}
}
```

### ■先頭大文字にすると公開関数や変数となる

```go
type Foo struct {
	ID   string // public いつでも触れる
	name string // private これは定義したときか、Foo structが置かれているファイル内でしか変更できない
}
```

### ■日付フォーマットの指定がよくあるやつだとyyyy-mm-ddとかだが、yyyyを2006って書くみたい

```go
fmt.Println(time.Now().Format("2006-01-02:15:04:05.000"))
// ↑のフォーマット指定で出力が下記。。。
// 2019-07-10:14:24:48.517 
```

`1月2日午後3時4分5秒2006年` ね？揃っているでしょ？的な軽い気持ちだったらしい。

（せめて、午前3時なら15って書かなくて済んだのになぁ。。）

プログラミングはウケ狙いで書くと後で恥ずかしかったり、訳分からんとなるのでコメントとか気を付けよう（戒め感ある）

※参考記事
[Goのtimeパッケージのリファレンスタイム（2006年1月2日）は何の日？](https://qiita.com/ruiu/items/5936b4c3bd6eb487c182)

※余談だが、↑の記事の方はGolangのコミット権限を持っているらしい。

### ■Object型をinterface{}と書く

```go
var obj interface{}
str := "str1"
obj = str
```

正確にはObject型じゃないらしいが、ざっくり理解としてはそれでいいはず。

### ■Javaとか他の言語で言うクラスが、フォルダ（package）単位

### ■フォルダとpackage名を合わせるのがお作法

### ■フォルダにファイルを複数置けるが、privateメソッドなども共有となるため、javaっぽいprivateがお望みならば、１フォルダ１ファイルとしたほうが分かりやすい。

フォルダが多くなりすぎるが、個人的には読みやすさ重視かなぁと。

### ■テストコードは循環参照などの問題が出ることがあるため、package名 + "_test"としたほうが良い（この状態でテストは動く）

### ■stringにnilが入らない。

### ■Goルーチンを使うなら、contextを引き継ぐと綺麗に終わらせられる

### ■buildしなくても動かせる

```bash
go run main.go
```

### ■go modulesに移行期（2019-06-19現在）で、Go1.13からデフォルトになる

### ■xerrorsパッケージも移行期（2019-06-19現在）で、Go1.13からデフォルトになる

### ■xhogeみたいにxパッケージ名のモジュールは、準標準パッケージ

### ■意外とシャドーイングが発生しやすいので気を付ける。出来るだけ別名使う？

```go
package main

import (
	"fmt"
)

func main() {
	str := "str1"
	if true {
		str := "str2"
		// str = "str2" // '='なら外側の変数に入る
		fmt.Println(str) // str2
	}
	fmt.Println(str) // str1
}
```

### ■リフレクション処理がマジでむずかしいのでつらい

### ■switch文がJavaなどと違う

[golangを基礎から学ぶ　制御構造編](https://qiita.com/high5/items/3fe34d2feeff2c11f5ca#switch)

> switch-caseのデフォルト動作は `fallthrough` ではない

途中条件でマッチしたら、その下には行かないということ。

### ■nilが型を持っているのでチェックには気を付けないといけない

```golang
package main

import "fmt"

func main() {
    var x *int32 = nil

    fmt.Println(x == nil) // true

    isnil(x)

    isnil2(x)
}

func isnil(x interface{}) {
    fmt.Println(x == nil) // false
}
func isnil2(x *int32) {
    fmt.Println(x == nil) // true
}
```

[play groundで試せます](https://play.golang.org/)

下記のようなコードなら判定できそうだが。。
https://github.com/gotestyourself/gotest.tools/blob/v3.0.0/assert/cmp/compare.go#L268

### ■特定行でスタックトレースを強制的に出したい（標準エラーに出力される？）

```golang
package main

import "runtime/debug"

func main() {
	debug.PrintStack()
}
```

### 最後に
---

この記事はどんどん追記していきますm(_ _)m