今週の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のはず
- 定数を見てて知らない概念がいてひよる
- コメント読むの好き
// 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 {
- 関数の中で関数を定義したり、varブロックでまとめて変数を定義したり
- 関数、必要とあれば100行以上書くこともあるのか(テスト厚めなパッケージ読んで再考したい。。)
context-aware
https://www.nttpc.co.jp/yougo/%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%BB%E3%82%A2%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%8D%E3%82%B9.html- チャンネルの写経が必要
- 生のerrorを見て自パッケージで扱いやすい型に包み直す関数が関数としてでなく変数として関数内に定義
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 }