■intのサイズはアーキテクチャによる
// 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を使っていったほうが良さそう。
a := [3]int64{1, 2, 3} // array
s := []int64{1, 2, 3} // slice
※下記記事が詳しい
Goのarrayとsliceを理解するときがきた
■mapのキー存在チェックは、下記のように書くと速い
map1 := map[string]string{"aaa": "aaa111"}
if v, ok := map1["aaa"]; ok {
fmt.Println(v) // pring aaa111
}
■interface{}からキャストするときにもokがある
func main() {
type Foo struct {
}
var e interface{}
e = Foo{}
if _, ok := e.(Foo); ok {
fmt.Println(e)
}
}
■先頭大文字にすると公開関数や変数となる
type Foo struct {
ID string // public いつでも触れる
name string // private これは定義したときか、Foo structが置かれているファイル内でしか変更できない
}
■日付フォーマットの指定がよくあるやつだとyyyy-mm-ddとかだが、yyyyを2006って書くみたい
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日)は何の日?
※余談だが、↑の記事の方はGolangのコミット権限を持っているらしい。
■Object型をinterface{}と書く
var obj interface{}
str := "str1"
obj = str
正確にはObject型じゃないらしいが、ざっくり理解としてはそれでいいはず。
■Javaとか他の言語で言うクラスが、フォルダ(package)単位
■フォルダとpackage名を合わせるのがお作法
■フォルダにファイルを複数置けるが、privateメソッドなども共有となるため、javaっぽいprivateがお望みならば、1フォルダ1ファイルとしたほうが分かりやすい。
フォルダが多くなりすぎるが、個人的には読みやすさ重視かなぁと。
■テストコードは循環参照などの問題が出ることがあるため、package名 + "_test"としたほうが良い(この状態でテストは動く)
■stringにnilが入らない。
■Goルーチンを使うなら、contextを引き継ぐと綺麗に終わらせられる
■buildしなくても動かせる
go run main.go
■go modulesに移行期(2019-06-19現在)で、Go1.13からデフォルトになる
■xerrorsパッケージも移行期(2019-06-19現在)で、Go1.13からデフォルトになる
■xhogeみたいにxパッケージ名のモジュールは、準標準パッケージ
■意外とシャドーイングが発生しやすいので気を付ける。出来るだけ別名使う?
package main
import (
"fmt"
)
func main() {
str := "str1"
if true {
str := "str2"
// str = "str2" // '='なら外側の変数に入る
fmt.Println(str) // str2
}
fmt.Println(str) // str1
}
■リフレクション処理がマジでむずかしいのでつらい
■switch文がJavaなどと違う
switch-caseのデフォルト動作は
fallthrough
ではない
途中条件でマッチしたら、その下には行かないということ。
■nilが型を持っているのでチェックには気を付けないといけない
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
}
下記のようなコードなら判定できそうだが。。
https://github.com/gotestyourself/gotest.tools/blob/v3.0.0/assert/cmp/compare.go#L268
■特定行でスタックトレースを強制的に出したい(標準エラーに出力される?)
package main
import "runtime/debug"
func main() {
debug.PrintStack()
}
最後に
この記事はどんどん追記していきますm(_ _)m