golang
golang紹介
Go言語のインストール - golang.jp
いまさら聞けないGo言語 - Qiita
初心者向けの導入
A Tour of Go
他言語プログラマがgolangの基本を押さえる為のまとめ
【Go】基本文法総まとめ
Go言語:文法基礎まとめ
各種リファレンス
言語仕様
標準ライブラリリファレンス
もう少し突っ込んだ内容
http://go.shibu.jp/effective_go.html
Github:https://github.com/golang/go
環境構築
golangのインストール
golangのパッケージマネージャ
go get rubyで言うgem
golangでコマンドライン引数を使う
Goでflagを使ってコマンドライン引数を扱う
変数
code:variable.go
// 基本的な宣言
var num int // = 0 golangでは、宣言すなわちインスタンス生成と捉えて良い
var slice []string // = []
var pointer *int // = nil
初期化に関しては、「何をするとインスタンスが生成されるのか」を意識しないと混乱する
code:instance.go
// 初期化集 どれが型宣言で、どれがインスタンス生成文かの見分けが難しい
var Bool bool = true
var Num int = 1
var Flo float64 = 0.5
var Word string = "hello"
var Rune rune = 'r'
var Array 2int = 2int{1, 2} // 添え字が変わるとダメ
var Squ 22int = 22int{{1,2},{3,4}}
var Sli []int = []int{1, 2} // 値入り
var Alo []int = make([]int, 10,10) // 0埋めアロケーション
var SliPtr []int = new(10int)0:10 // 上と同じ動作
var Hash mapstringint = mapstringint{"hoge": 10}
var Pointer *int = new(int) // = 0 newはポインタを返す
var Struct struct{x int} = struct{x int}{x: 10} // この辺からtype使わないと混乱する
StructMini := struct{y int}{y:20} // 型推論を利用した即席構造体
var Func func(x int) = func(x int){ } // 引数や戻り値が変わるとダメ
CallBack := func(x int) { } // 型推論を利用した無名関数
var Any interface{} = 10 // interface{} はあまりに特殊なんで、こういう型だと思った方が良い
// typeを絡めたstruct
type Point struct{
x, y int
}
func (p Point)Add(to Point) Point {
return Point{x:(p.x + to.x), y:(p.y+to.y)}
}
type Addable interface {
Add(to Point) Point
}
var Origin Point = Point{x:0, y:0}
var Adder interface{Add(to Point) Point} = Origin
var addable Addable = Origin
Adder.Add(addable) // NG addableはPoint型ではなくAddable型
Adder.Add(Origin) // OK
Origin.Add(Adder) // NG Adderは「interface{Add(to Point) Point}型」
スライス[]int、マップmap[string]int、チャネルは参照型
参考
Golang速習: interface{}型とinterface
文字列
サマリ
https://gist.github.com/takahashi-kenryu/5e2275925554b818b1e24d5909723d5f
サンプルで学ぶ Go 言語:String Formatting
rune型
golangには、マルチバイトを意識したchar型とも呼ぶべきrune型(ルーン型)が存在する
runeを意識したstring操作例
要は、一旦runeのスライスに変換してね。って事
文字数カウント時に1バイト文字か2バイト文字か気にしなくて良いの助かる
ただ、実態はint32型らしく、そのまま取り回すと数字になるので、stringに変換して使う
意図的にruneを作るならr := 'r' (シングルクォート)
実態はInt32
足したり引いたり出来る
中身は、文字のUnicode codepoint表現
'A' で生成出来る。シングルクォート。
正規表現
https://www.wakuwakubank.com/posts/780-go-string/#regexp-package
関連パッケージ
https://golang.org/pkg/strings/
https://golang.org/pkg/fmt/
https://golang.org/pkg/strconv/
https://golang.org/pkg/text/
https://golang.org/pkg/regexp/
参考
Go言語(golang) 文字列/string
文字列操作と関連パッケージ(fmt, strings, strconv)
for文いろいろ
code:for.go
for i := 0; i < 10; i++ { } // 標準的な
for { } // 無限ループ
for i < 10 { } // 条件のみ
for i, v := range array { } // forEachのような
break や continue も使える
Switch文
code:switch.go
a := 10
switch a { // 基本形
case 1:
fmt.Println("One") // Breakeは要らない
case 2: fallthrough // 代わりに、下のcaseに続ける場合fallthroughが必要
default:
fmt.Println("Default")
}
switch {
case a < 5:
fmt.Println("Less Then 5") // caseに式が書ける
}
配列
code:array.go
//参照用配列
var arr2string = 2string{"Ruby","Golang"}
//ex1:配列とは異なり長さ指定の必要なし
var slice1 []string //スライス(1)
var slice2 []string = []string{"Ruby", "Golang"} //スライス(2)
//ex2:配列から要素を取り出し参照する形での宣言が可能
var slice3 = arr0:2 //スライス(3)
//ex2:make()を利用した宣言が可能
var slice4 = make([]string,2,2) //スライス(4) * make(型, 長さ, キャパシティ)
//ex3:配列とは異なり要素の追加が可能
//append は新しいスライスを返すことに注意
slice5 := [] string{"JavaScript"}
newSlice := append(slice5, "Ruby") //sliceに"Ruby"を追加
//ex4:長さ(length)と容量(capacity)の両方を持っている。
//長さ(length) は、それに含まれる要素の数
//容量(capacity) は、スライスの最初の要素から数えて、元となる配列の要素数
fmt.Println(len(slice)) //=> 2
fmt.Println(cap(slice)) //=> 2
//ex5:型が一致している場合、他のスライスに代入することが可能。
var slice2[]string //sliceと同型slice2を作成
slice2 = slice //sliceをslice2に代入
fmt.Println(slice2) //=>Golang Ruby
//ex6:スライスのゼロ値は nil
var slice3 []int
fmt.Println(slice3, len(slice), cap(slice)) //=> [] 0 0
if slice3 == nil {
fmt.Println("nil!") //=> nil!
//sliceの値がnilの場合にnil!を表示する。
}
配列操作系、所謂コレクションAPIは存在しないので筋肉で頑張る必要がある・・・
関数
code:go
type Int int // 組み込み型はレシーバにできないので独自型を定義
func (this *Int)add(a Int) (b Int) { // レシーバの型、関数名、引数、戻り値の順で定義
b = this + a
return
}
type OnClick func(b Button) で、デリゲートのような物が作れる
基本的に値渡しでやり取りされるので、大規模structなんかを渡すようであれば、ポインタにする方が良い
golangにおける型定義
structの中にstructを入れる場合、フィールド名を省略する記法がある
https://golang.org/ref/spec#Struct_types
型で宣言されているが、明示的なフィールド名を持たないフィールドを埋め込みフィールドと呼ぶ。埋め込みフィールドは,型名Tまたは非インタフェース型名*Tへのポインタとして指定されなければならず,T自体はポインタ型であってはならない。非修飾の型名はフィールド名として機能します。
構造体 x の埋め込みフィールドのフィールドまたはメソッド f は、x.f がそのフィールドまたはメソッド f を示す合法的なセレクタである場合、昇格と呼ばれます。
プロモートされたフィールドは、構造体の複合リテラルでフィールド名として使用できないことを除いて、構造体の通常のフィールドのように動作します。
構造体の型Sと定義された型Tがある場合、プロモートされたメソッドは以下のように構造体のメソッド・セットに含まれます。
Sに埋め込みフィールドTが含まれている場合、Sと*Sのメソッドセットには、レシーバTを持つプロモートされたメソッドが含まれます。
Sが埋め込みフィールド*Tを含む場合、Sと*Sのメソッドセットは、レシーバTまたは*Tを持つプロモートされたメソッドを両方とも含みます。
要するに
code:go
type Point struct{ x, y int }
type PointWithName struct{
Point
Name string
}
p := PointWithName {
Name: "origin",
Point: Point{ x:10, y:20 },
}
p.x = 10
code:go
// 実態とポインタの使い分け
type Point struct{ x, y int }
type PointWithNameReal struct{
Point
Name string
}
type PointWithNamePoint struct{
*Point
Name string
}
var pr PointWithNameReal
pr.x = 10 // OK 実態宣言なら宣言した時点でインスタンスが作られるので通る
var pp PointWithNamePoint
pp.x = 10 // NG インスタンスが無いので代入先が無い
pp.Point = &Point{}
pp.x = 10 // OK インスタンス入れた
実態型を埋め込むと継承、ポインタ型を埋め込むとDIコンテナ的な移譲に向いたふるまいをする
ドキュメントコメント
godoc -http=:8080 でドキュメント生成できる
参考
go doc の使い方・コメントを書いて、ちゃんと読む
エラーハンドリング
try-cachをあまり見かけない。
多値返却で第2戻り値にエラーオブジェクトを入れるのをよく見る
戻り値がvoidであれば、ワンライナーっぽく書いてるのをよく見る
code:go
if err := json.Unmarshal(hoge, &fuga); err != nil {
return nil, err
}
詰まりメモ
使っていない変数があるとコンパイルが通らない
複数の戻り値がある関数で、使わないものがあるなら_で逃げられる
no new variables on left side of :=
code:go
funt hoge() (a int) {
a := 1 // no new variables on left side of :=
return
}
名前付き戻り値を定義すると、関数実行直前で宣言されるため、再宣言になりエラー
:=を=にすると通る
typeで定義した組み込み型は、元の型へのオートボクシングが行えない
code:go
type ModelId string
var hoge ModelId
hoge = "hoge"
log.Printf(hoge) // コンパイルエラー
log.Printf(string(hoge)) // "hoge"
jsonデシリアライズ用構造体でワーニング
【golang】struct field XXXX has json tag but is not exported - コガネブログ
error strings should not be capitalized 対応
エラーメッセージの1文字目を大文字にしてはいけないらしい
ログ周り
https://www.kaoriya.net/blog/2018/12/16/