初級者向けGoの落とし穴と解説 / Traps and Explanations in Go

初級者向けGoの落とし穴と解説 / Traps and Explanations in Go

Go(Un)Conference(Goあんこ)LT大会 3kg
https://gounconference.connpass.com/event/92794/

資料中の参考リンクなどは以下にまとめてあります。
https://budougumi0617.github.io/2018/07/26/presentation-gounco-lt3/

Eb6be531bcfaa99714d8d3b48665a5a9?s=128

Yoichiro Shimizu

July 26, 2018
Tweet

Transcript

  1. 初級者向け Goの落とし穴と解説 Go(Un)Conference LT #3, JULY 26 2018 Yoichiro Shimizu

    freee k.k. @budougumi0617
  2. • 清水 陽一郎 @budougumi0617 • freee 株式会社 ◦ Backend /

    Desktop-App Engineer ◦ Go / Ruby on Rails / .NET • golang.tokyo 運営 • Blog ◦ https://budougumi0617.github.io/ 自己紹介
  3. About Gopher SECTION ZERO

  4. { On conppass 00. About gopher

  5. • Go Brand Book ◦ https://golang.org/s/brandbook Gopher IS NO DEAD

    00. About gopher
  6. Today’s contents About Gopher 00 How to study Go Traps

    and explanations Today’s summary 01 02 03
  7. How to study Go SECTION ONE

  8. { Goのデザインポリシー Each language feature should be easy to understand.

    01. How to study Go
  9. How do you studying Go? • Goは簡単というけれど、どう覚える? ◦ Read spec?

    ◦ A Tour of Go? ◦ On the job? 01. How to study Go
  10. There are many traps • 基本的な書き方はすぐ理解できる • とはいえ、 曖昧な理解だとハマることも多い •

    知らないとググれもしない問題 01. How to study Go
  11. 例:曖昧な理解だとハマること1 package main import "fmt" func add(a []int) { a

    = append(a, 4) fmt.Printf("%v\n", a) // [1 2 3 4] } func main() { a := []int{1, 2, 3} fmt.Printf("%v\n", a) // [1 2 3] add(a) fmt.Printf("%v\n", a) // [1 2 3] } https://play.golang.org/p/A8fouhhtLQZ 呼び出し先で 引数sliceを appendする 01. How to study Go
  12. 例:曖昧な理解だとハマること2 package main import ( "fmt" ) func main() {

    go fmt.Println("go!") } https://play.golang.org/p/PUoHxeT-RJu main goroutineが 先に死んで 何も起きない @GROOVEX_SWのGoクイズより 01. How to study Go
  13. What can we do? • 必要なのは体系的な仕様の学習 • だけど全部は難しい • •

    愚者は経験に学び、賢者は歴史に学ぶ 01. How to study Go
  14. Today's goal • 対象:ひと通り仕様を理解している人 • よくあるハマりポイントを解説 ◦ 一度はハマる落とし穴 ◦ へぇ!ってなる仕様

    • 「それは知らなかった」という 何かを持って帰ってもらうこと 01. How to study Go
  15. { 引用元 - プログラミング言語Go • Pros ◦ 日本語書籍で一番体系的 ◦ 設計思想にも言及している

    • Cons ◦ ~ Go1.6なので contextなどは未言及 ◦ database/sql等も薄い 01. How to study Go
  16. Traps and Explanations SECTION TWO

  17. Loop with defer package main import ( "fmt" ) func

    useHeavyResource() { for i := 0; i < 5; i++ { defer func() { fmt.Println("Released") }() // Do something with resource } fmt.Println("Finished") } func main() { useHeavyResource() } https://play.golang.org/p/q_V9E1H5Jhy What output? 02. Traps and explanations
  18. P167 5.8 遅延関数呼び出し 遅延された関数はそれを含んで いる関数の最後まで実行されま せんので、ループ内のdefer文は 注意深く確認する必要がありま す。

  19. Map package main import ( "fmt" ) type s struct

    { i int s []string } func main() { m := new(map[s]string) fmt.Printf("%v\n", m) } https://play.golang.org/p/rKforjFi2CW Why error? 02. Traps and explanations
  20. P105 4.3 マップ 与えられたキーがマップ内にすで にあるキーと等しいかどうか検査 できるように、キーの型Kは==を 使って比較可能でなければなりま せん。

  21. Interface package main import ( "bytes" "io" ) func log(buf

    io.Writer, s string) { if buf != nil { buf.Write([]byte(s)) } } func main() { var b *bytes.Buffer = nil log(b, "foo") } https://play.golang.org/p/QzK9wJQXwcS Why panic? 02. Traps and explanations
  22. P213 7.5 インターフェース値 nilポインタを含む インターフェースはnilではない

  23. Captured value package main import ( "fmt" "time" ) func

    main() { for i := 0; i < 5; i++ { go func() { fmt.Printf("%d", i) }() } time.Sleep(2 * time.Second) } https://play.golang.org/p/24O7H2cQZLf Where is problem? 02. Traps and explanations
  24. P160 5.6.1 警告:ループ変数の補足 ループによって作成されるすべて の関数値は、同じ変数を「補足」し て共有します。 つまり特定の瞬間の値ではなく、 アドレス化可能なメモリの位置を 共有します。

  25. Local variable 1 package main import ( "fmt" ) func

    main() { x := "hello" for _, x := range x { x := x + 'A' - 'a' fmt.Printf("%c", x) } } https://play.golang.org/p/ljulBLJZs6k Compilable? 02. Traps and explanations
  26. P52 2.7 スコープ レキシカルブロックは関数内で任 意の深さまでネストできますので、 一つのローカル宣言が別のロー カル宣言を隠蔽することができま す。

  27. Local variable 2 package main import ( "fmt" ) func

    main() { if x := 10; x == -1 { // do something... } else if y := 20; y == -1 { // do something... } else { fmt.Printf("%d %d", x, y) } } https://play.golang.org/p/6NH44WjXOz- Compilable? 02. Traps and explanations
  28. P52 2.7 スコープ for文と同様に、if文とswitch文 もそれぞれの本体ブロックに加え て暗黙のブロックを生み出しま す。

  29. Notification channel • Which best? ◦ done := make(chan int)

    ◦ done := make(chan struct{})
  30. Size of empty struct is zero package main import (

    "fmt" "reflect" ) func main() { var i int var s struct{} fmt.Printf("%v\n", reflect.TypeOf(i).Size()) // 4 fmt.Printf("%v\n", reflect.TypeOf(s).Size()) // 0 } https://play.golang.org/p/nZqAFEZs48J チャネルの型は重 要ではありません ので、大きさがゼロ であるstruct{}を 使います。 P278 8.6 例:平行ウェブクローラ 02. Traps and explanations
  31. 公開されていない フィールドもリフレ クションでは見える ことに注意してくだ さい。 Visibility private field package main

    import ( "fmt" "os" "reflect" ) func main() { v := reflect.ValueOf(os.Stderr) // os.File.(*file).name fmt.Printf("%v\n", v.Elem().Field(0).Elem().FieldByName("name")) } https://play.golang.org/p/u8-5-kWyzGI P387 12.3 Display:再帰的な値の表示 02. Traps and explanations
  32. Today’s Summary SECTION THREE

  33. Today's summary • Gopherくんは不滅 • 一度はハマる落とし穴/仕様を紹介 • そんな落とし穴も本で言及されていた • 体系的な言語仕様の学習は大切

    03. Today’s summary