Slide 1

Slide 1 text

Go初心者が躓いたところ ~ Difficulty of Go for Beginners ~ 1 2019/03/26 mercari.go #7 @MasakiKuwako

Slide 2

Slide 2 text

自己紹介 アカウント ● github: kuwako / twitter: @MasakiKuwako 経歴 ● WEBメディアの会社に新卒で入って 4年 ○ PHP/JS/AndroidJava/Scala ● アドテクの会社で1年 ○ PHP/JS/Scala ● 2018/12 メルカリ入社 ○ カスタマーサポート向けのツールを作ってます ○ PHP/JS/Go

Slide 3

Slide 3 text

自己紹介 アカウント ● github: kuwako / twitter: @MasakiKuwako 経歴 ● WEBメディアの会社に新卒で入って 4年 ○ PHP/JS/AndroidJava/Scala ● アドテクの会社で1年 ○ PHP/JS/Scala ● 2018/12 メルカリ入社 ○ カスタマーサポート向けのツールを作ってます ○ PHP/JS/Go ○ Go歴は1ヶ月程度です。ご容赦ください。

Slide 4

Slide 4 text

agenda 1. ポインタの宣言とデリファレンス 2. 構造体の初期化 3. デバッグ 4. package名 5. unexportなmethodのテスト 6. シンタックスシュガーによる型の解釈の変換

Slide 5

Slide 5 text

ポインタの宣言とデリファレンス 初見だと1と3がややこしい (今でもたまにミスる) 1. *AnimalでAnimal型のポインタの宣言 2. &Animal{} でAnimal型のポインタを生成 3. *a でポインタの実体を渡す (デリファレンス)

Slide 6

Slide 6 text

構造体の初期化1 new(Animal) と &Animal{ } の意味は同じ

Slide 7

Slide 7 text

構造体の初期化2 Effective Go より意訳 Goのnewはメモリの割り当てを行う組み 込み関数ですが、他言語のnewの多くと は異なり、メモリの初期化ではなく、ゼロ 化のみを行います。 &Animal{ } 形式は一行で初期化できる a := &Animal{ “Pao”, 5 } => ok b := new(Animal{ “Pao”, 5 }) => ng

Slide 8

Slide 8 text

デバッグ 変数の中身見たいときは fmt.Printf(“%#v”, hoge) が便利 PHPerなのでvar_dump()的な関数探してた

Slide 9

Slide 9 text

package名 model - item.go => package model - user.go => package model - item_test.go => package model_test - user_test.go => package model_test 同じディレクトリには同じpackage名しか使えない ※ _test.go は除く(testも{package名}_testしか使えない) golang.org より意訳 Goの規約では、パッケージ名はインポートパスの最後 の要素であるべきです。 例えば、"crypto/rot13"であればrot13と名付けられるべ きです。 ただし、実行可能コマンドは常に package mainでなけ ればなりません。

Slide 10

Slide 10 text

unexportなメソッドのテスト modelパッケージ内のunexportなメソッドechoをテストするためのexport_test.go 大きく2種類ある。package model をテストする際 1. model_test.go のpackageもmodelにする (package内なのでアクセス可能) 2. model_test.go のpackageはmodel_testにし、別途 export_test.goを使う

Slide 11

Slide 11 text

シンタックスシュガーによる型の解釈の変換 ポインタレシーバのメソッドでも型の解釈が変換されて値型からの実行が可能

Slide 12

Slide 12 text

突然ですが

Slide 13

Slide 13 text

ここで問題です

Slide 14

Slide 14 text

次のうち 動かないのはどれ

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

答え

Slide 17

Slide 17 text

2. 値がポインタレシーバのメソッドをもっている場合 Animal does not implement Creature (echo method has pointer receiver) と言われる => interfaceを通すと、値型 -> ポインタの型の解釈の変換ができない

Slide 18

Slide 18 text

Why?

Slide 19

Slide 19 text

interfaceの挙動について Why value stored in an interface is not addressable in Golang When an interface value is created, the value that is wrapped in the interface is copied. It is therefore not possible to take its address, and even if you did, using a pointer to the interface value would have unexpected effects (ie. unable to alter the original copied value). インターフェース値が作成されると、そのインターフェースにラップされている値がコピーされます。 そのため、 そのアドレスを取得することはできません。たとえ行ったとしても、インターフェース値へのポインターを使用す ると、予期しない結果が生じる可能性があります(つまり、元のコピーされた値を変更できません)。 interface値を使うとき、値がコピーされて別のメモリ領域に格納される => 実体からポインタへの型の解釈の変換は不可能

Slide 20

Slide 20 text

検証してみた (ポインタの場合) ポインタ x ポインタレシーバの場合 ポインタ自体がコピーされるので、 interface値にしても ポインタが変わっていない

Slide 21

Slide 21 text

検証してみた (値の場合) 値 x 値レシーバの場合 interfaceに保存するときに値がコピーされて別のメモ リ領域に保存されるので、 interface値にするとポイン タが変わっている => 値から元のポインタへの解釈の変換ができない ==> (推測) echo()がポインタレシーバだった場合はメ ソッド側からは渡された変数が echo()を実装していな いように見えるのでAnimal does not implement Creature と言われた

Slide 22

Slide 22 text

Go楽しい

Slide 23

Slide 23 text

Thank you for listening!