CA22 golang輪読会
毎週火曜/木曜日21時〜の輪読会のコメントを残す場所
Goの仕様書輪読会で学んだ知見を記録していく
4/27 22時〜typeの初めからslice型まで
参考
5/4 22時〜pointer から型の終わりの部分まで
参考
5/11 22時〜properties of types and values から blocksまで
参考
5/18 21時〜declarations and scope から iotaまで
const A = 2
const A = 2←ConstDecl
A = 2 ← ConstSpec
参考
- https://qiita.com/tenntenn/items/7c70e3451ac783999b4f
- https://www.geeksforgeeks.org/what-is-blank-identifierunderscore-in-golang/#:~:text=_(underscore) in Golang is,unused variable using Blank Identifier.&text=It hides the variable's values and makes the program readable.
- https://syumai.hateblo.jp/entry/2020/12/10/020510
5/25 21時〜
Type declarations から Method declarations まで
参考
-
https://speakerdeck.com/dqneo/go-language-underlying-type
underlying型についてのスライド -
https://zenn.dev/nobishii/articles/133142a79e2c76b2f1bd
type definition
5/27 21時〜net/http
パッケージを読む
- Handle関数とHandleFuncは何が違うのか
- ListenAndServeの中では何が行われているのか
- サーバーの処理が停止されるまでどうやってリクエストを待っているのか
- どうやってHandleとListenAndServeでやりとりをしているのか
などについてしれた。
ListenAndServeの中ではコネクションだけでなくファイルのi/oの処理っぽいのもswitchで分岐されていて、丁寧に抽象化することで統一しているんだと感じた。
TCP/IP/UDPやその他OSI標準モデルに基づく処理がされていそうで知識のなさを実感した。
勉強し直してもう一度読みたい。
参考
-
https://qiita.com/immrshc/items/1d1c64d05f7e72e31a98
net/httpのパッケージについて非常に丁寧にまとまっている
6/1 21時〜
expressions/opperands から Method values まで
参考
6/3 21時〜
ioとcontextを読んだ
先週いきなりnet/httpからやってしまい、他のパッケージでもよく出てくるであろうこの二つを先に読んだ方が良いと思ったので先に読む、ioだけのつもりだったが、すぐ終わったのでcontextも読んだ。
- io.Reader io.Writerは何がうれしいのか
- contextパッケージとはそもそも何をしているのか
- context.Background、context.WithCancel、context.WithTimeoutなどはどういう時に使用されるのか。
- この辺はblogに詳細に書いてあり非常にわかりやすかった。
contextに関しては全く知らないから大体見れば何がしたいかわかるぐらいにはなれたと思う、goroutineの制御などに関しては実際に触ってみないとわからない部分が多いと思うので、触っていくうちにマスターできれば良さそう。
参考
-
https://qiita.com/ktnyt/items/8ede94469ba8b1399b12
io.Readerは何がうれしいか -
https://onemuri.space/note/Y2-pkc8rI/
io.Writerは何が嬉しいか -
https://future-architect.github.io/articles/20210210/
- ioパッケージのところにv1.16から
io os
に統一されると書いてあったのでその補足
- ioパッケージのところにv1.16から
-
https://zenn.dev/hsaki/books/golang-io-package
すごくよくまとまっている、一度は読むべき
shampuくんが纏めてくれたので追記
package main
import (
"context"
"fmt"
"io"
"os"
"os/signal"
"sync"
"time"
)
type AwesomeWriter struct{}
func (AwesomeWriter) Write(b []byte) (int, error) {
fmt.Printf("Awesome %s\n", string(b))
return len(b), nil
}
func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
aw := AwesomeWriter{}
wg := sync.WaitGroup{}
wg.Add(1)
go tickWrite(ctx, aw, &wg)
wg.Wait()
}
// 一定時間でWriteする
func tickWrite(ctx context.Context, w io.Writer, wg *sync.WaitGroup) {
defer wg.Done()
ticker := time.NewTicker(5 * time.Second)
for {
select {
case <-ticker.C:
_, _ = w.Write([]byte("shanpu"))
case <-ctx.Done():
fmt.Println("Goodby")
return
}
}
}
6/8 21時〜
expressions/index expressions からcomparison operator まで
参考
配列操作で a[low : high : max]
こんな書き方があることをしれた、自分では書かないと思うけど
func Greeting(prefix string, who ...string)
の書き方は知っていたが、 Greeting("goodbye:", s...)
の書き方は知らなかったので新たな発見があった。
bit演算はすることないと思っているので必要なときになったら勉強します。
6/10 21時〜reflect
パッケージを読む
- どのように空interfaceからキャストしているのか
- switch文で行う
type assersion
とかとどのように異なっているのか - それぞれのinterfaceの型情報と値についてどのように保持しているのか
などについてしれた。
switch文でかなり分岐をしているのでreflectの処理は重そうで内部的にreflectを使用している、 gorm
などのリッチなORマッパーや encoding/json
などはパフォーマンスを気にするなら使用しない方が良さそう。
interfaceはgoの内部で
type interfaceType struct {
typ *rtype // 型情報へのポインタ
ptr unsafe.Pointer // 値のアドレス
}
となっていて、それぞれのinterfaceで型情報へのポインタと値を保持している、そのためにswitch文とかで
switch v := i.(type) {
case int:
fmt.Printf("Twice %v is %v\n", v, v*2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v))
default:
fmt.Printf("I don't know about type %T!\n", v)
}
とかでアサーションできる、しっかり読んでいないけどおそらくhoge.(type)
って明示的に書かないとptrの方を指すんだと思う。
参考
-
https://tikasan.hatenablog.com/entry/2017/07/19/173053
ドキュメントの日本語訳があった。 - https://www.m3tech.blog/entry/2020/03/18/140000
-
https://engineering.mercari.com/blog/entry/1599563768-081104c850/
上で言っていたencoding/jsonが重い話
6/15 21時〜
expressions/comparison operators からorder of evaluation まで
評価順序の話は今までは当たり前に思っていたことだが、文章にすると
var a, b, c = f() + v(), g(), sqr(u()) + v()
func f() int { return c }
func g() int { return a }
func sqr(x int) int { return x*x }
// functions u and v are independent of all other variables and functions
ネストの中身から解決してそのあとは前から
a := 1
f := func() int { a++; return a }
x := []int{a, f()} // x may be [1, 2] or [2, 2]: evaluation order between a and f() is not specified
m := map[int]int{a: 1, a: 2} // m may be {2: 1} or {2: 2}: evaluation order between the two map assignments is not specified
n := map[int]int{a: f()} // n may be {2: 3} or {3: 3}: evaluation order between the key and the value is not specified
3行目の x may be [1, 2] or [2, 2]: evaluation order between a and f() is not specified
がずっと [2,2] が出力されてよく分からなかった。
そもそもグローバルに定義されているものを引数に渡すわけでもなく更新するというこの書き方をするのが原因だと思うけど、気をつける。
参考
6/17 21時〜 encoding/json
パッケージを読む
参考
-
https://engineering.mercari.com/blog/entry/1599563768-081104c850/
encoding/json
は遅いという記事 -
https://play.golang.org/p/HDG_lEqW6zu
エンコードとデコード処理のサンプル
6/22 21時〜statements/terminating statementsからswitch statements
特筆するようなことはなかった、type switchのところで hoge.(type)
ってやらなかったら値を指すんだなーって話をしてた
6/24 21時〜database/sql
を読む