Gopher道場3回目

   · ☕ 5 min read
🏷️
  • #go
  • コマンドラインツール

    プログラム引数

    flagパッケージ

    入出力の抽象化

    io.Readerとio.Writer
    読み書きに関するものを抽象化
    書き込み先や読み込みもとを意識せずに使える
    ioする箇所とエンコーディングの箇所を切り離せる
    Unix のパイプのように、io.Readerとio.Writeをくっつけられうので便利

    • fmt.Fprintf(os.Stderr, “エラー”)
      • コマンドツールを作るときのコツは、コマンドが汚れないようにすること。エラーにしておくとパイプ先に渡されない。

    プログラムの終了

    Os.Exit
    0が成功, 0以外を指定してやる

    log.fatal だと、終了コードは1に限定される。
    基本的にはlog.fatal は使うことはないと認識しておく。
    特にmainパッケージ以外では使わない。

    1行ずつ読み込む

    Buffo.Scannerを使用する

    ファイルを扱う

    osパッケージを使う
    os.Createで書き込みを行なった場合は、Closeの前にエラー処理をする。

    defer

    同ブロック内でdeferを複数行なった場合、最後のdeferから順に実行される。スタック形式。

    ファイルパスを扱う

    Path/filepathパッケージを使う

    OSに寄らないファイルパスの処理が行える

    ディレクトリをウォークする

    Filepath.Walkを使う

    抽象化

    インタフェース

    Goではインターフェースでしか抽象化することができない
    implementsを使用しない
    モックを使う時などは、interface を先に自分で規定して使うと良い

    1
    2
    3
    4
    5
    6
    
    type Stringer interface {
    	String() string
    }
    // インタフェースを実装していることになる
    var s Stringer = Hex(100)
    fmt.Println(s.String())
    

    empty interface

    interfaceのメソッドの集合が空集合

    1
    2
    3
    
    var v interface{}
    v = 100
    v = "hoge"
    

    スライスとインタフェース

    実装していてもスライスは互換がない,

    インタフェースの実装チェック

    型スイッチ

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    var i interface{}
    i = 100
    switch v := i.(type) {
    	case int:
    		fmt.Println(v*2)
    	case string:
    		fmt.Println(v+"hoge")
    	default:
    		fmt.Println("default")
    }
    

    インタフェースの設計

    • 共通点を抜き出して実装しない
      • だいたい失敗する
    • 抽象化を本当にしなければいけない部分のみ抽象化する

    埋め込みとインターフェース

    埋め込み … 名前のないフィールドとして、構造体に構造体を組み込む
    楽にアクセスできる。

    1
    2
    3
    4
    5
    6
    7
    8
    
    type Hoge struct {N int}
    type Fuga struct {Hoge}
    
    f := Fuga{Hoge{N:100}}
    // Hoge型のフィールドにアクセスできる
    fmt.Println(f.N)
    // 型名を指定してアクセスできる
    fmt.Println(f.Hoge.N)
    

    インタフェースの合成

    インタフェースにインタフェースを埋め込む
    埋め込まれたインタフェースの実装を変えた時も、埋め込み元の変更の必要がない

    エラー処理

    エラー

    errorインタフェース

    Ras cox のエラーについての話が良い

    エラーに文脈を持たせる

    何をしようとした時にエラーが起きたか知りたい
    errors.Wrapを使うとエラーをラップできる
    errors.Causeを使うと元のエラーが取得できる

    パニックとリカバー

    パニック
    基本的にパニックは使わない。改善不良、回復不可である時。panicは書くな。

    リカバー
    パニックを回復する。パニックの際は処理が中断するが、deferは実行される。なのでリカバーはdeferで実行される。

    Exceptionとは全く異なる。同じように使わない。

    テストとテスタビリティ

    testingパッケージ

    関数の名前の頭にTestがある、引数にtestingをとっているものを実行

    テストのパッケージは、テスト対象と分けておく

    Parallel
    テスト関数を複数同時に実行できる。早くできる

    ベンチマーク
    速さの証明。速さを売りにしているライブラリには書かれていることが多い。

    testing/quick
    境界値を見て、ランダムにブラックボックスを実行してくれる。

    テスティングフレームワーク testify すらも、あまり使わない方が良い
    アサーションのライブラリをプロジェクト内で作ることは良い。
    テストのための学習コストが必要になるのは、よくない。
    go-cmp を使うと、diffを撮ったり、0.0001などの許容をしてくれたりする。

    Exampleテスト

    ExampleをREAD.me に書いておくと、修正を忘れがち。

    サブテストとテーブル駆動テスト

    テストケースとテストロジックの分離

    シャドーイングに注意!

    テストヘルパー

    テストヘルパーは、準備のためのヘルパーであり、本ロジックのテストには使用するものではない。
    なので、基本的にはエラーを返さない。t.Fatalで落とす。
    落ちたときの情報を整理してくれる。

    てスタビリティ

    モックを使う理由
    テストの再現性を担保するため。

    モックを使う場合は基本的にインタフェースを使用する。

    環境変数を構造体にマッピングしてくれるパッケージがある。Third partyで viperなど。spf13さん

    testdata
    _で始まるディレクトリ、testdataという名前のディレクトリはパッケージに含まれない。

    export_test.go

    依存しているものを羅列するために書く

    宿題

    • タイピングゲーム
      • 細かいルールは適当に決めて、宣言、
        • 制限時間内
        • キーボードが待ち受けている時間の制御にgoroutine
    • 分割ダウンロード
      • goroutineで複数投げて、取得後に合体させる。
    Share on

    whasse
    WRITTEN BY
    whasse
    Web Developer