woshidan's loose leaf

ぼんやり勉強しています

今週のGo

週5以上活動していればよい感じで。

  • 以下のようなコードを動かしながら、関数値gの中でその値が定義された関数f内の変数Aを利用すると、関数値gは変数Aの参照を持っているのだなぁ、という確認をしていた
  var once sync.Once

  onceFunc := func() {
    once.Do(func() { fmt.Println("A") })
  }

  func main() {
    var once sync.Once

    firstFunc := func() {
      once.Do(func() { fmt.Println("A") })
    }

    secondFunc := func() {
      once.Do(func() { fmt.Println("A") })
    }

    firstFunc() // 1回しか実行されない
    secondFunc()
  }

  // $ go run sync.go 
  // A
  func main() {
    var cnt int

    firstFunc := func() {
      cnt++
      fmt.Println("A: ", cnt)
    }

    secondFunc := func() {
      cnt++
      fmt.Println("B: ", cnt)
    }

    firstFunc()
    secondFunc()
  }

  // $ go run sync.go 
  // A:  1
  // B:  2 // それぞれの関数値で値を定義した時点でのコピーを持っているなら、ここは1のはず
  • 定数を見てて知らない概念がいてひよる
    • TLSDialTimeout TLSDialTimeout = 20 * time.Second
      • TLSにDialという概念がある..?
      • 通信が完了するまで待つ時間
    • HTTPClientTimeout HTTPClientTimeout = 60 * time.Second
      • 個々の通信自体の時間 + リダイレクト + リクエスト・レスポンスの読み書き合計したタイムアウト
    • TCPKeepAlive = 60 * time.Second
      • ネットワーク接続のキープアライブの時間
      • キープアライブ自信ねえ...
  • コメント読むの好き
    • // We add : because we include :port as part of host. のように一つずつ値について説明してあるやつとか
  • 値を直接入力させず、値を設定するメソッドを置いている
  // 値を直接入力させず、値を設定するメソッドを置いている
  // Development sets the Client to use the APNs development push endpoint.
  func (c *Client) Development() *Client {
    c.Host = HostDevelopment
    return c
  }

  // Production sets the Client to use the APNs production push endpoint.
  func (c *Client) Production() *Client {
    c.Host = HostProduction
    return c
  }
  • golintのusage が結構愚直に書いてあった
  func usage() {
    fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
    fmt.Fprintf(os.Stderr, "\tgolint [flags] # runs on package in current directory\n")
    fmt.Fprintf(os.Stderr, "\tgolint [flags] [packages]\n")
    fmt.Fprintf(os.Stderr, "\tgolint [flags] [directories] # where a '/...' suffix includes all sub-directories\n")
    fmt.Fprintf(os.Stderr, "\tgolint [flags] [files] # all must belong to a single package\n")
    fmt.Fprintf(os.Stderr, "Flags:\n")
    flag.PrintDefaults()
  }
  • 分岐について自分個人は早期returnしたくなるところで if { 短い } else { 長い }
  func main() {
    flag.Usage = usage
    flag.Parse()

    if flag.NArg() == 0 {
      lintDir(".")
    } else {
    uerr := func(err error) error {
      // the body may have been closed already by c.send()
      if !reqBodyClosed {
        req.closeBody()
      }
      method := valueOrDefault(reqs[0].Method, "GET")
      var urlStr string
      if resp != nil && resp.Request != nil {
        urlStr = resp.Request.URL.String()
      } else {
        urlStr = req.URL.String()
      }
      return &url.Error{
        Op:  method[:1] + strings.ToLower(method[1:]),
        URL: urlStr,
        Err: err,
      }
    }
  • switchに式を与えず case に 式を書くのも普通にやるようだ
  func unhex(c byte) byte {
    switch {
    case '0' <= c && c <= '9':
      return c - '0'
    case 'a' <= c && c <= 'f':
      return c - 'a' + 10
    case 'A' <= c && c <= 'F':
      return c - 'A' + 10
    }
    return 0
  }