Open16

CA22 golang輪読会

ryota kiseryota kise

5/27 21時〜
https://golang.org/pkg/net/http/
net/httpパッケージを読む

  • Handle関数とHandleFuncは何が違うのか
  • ListenAndServeの中では何が行われているのか
  • サーバーの処理が停止されるまでどうやってリクエストを待っているのか
  • どうやってHandleとListenAndServeでやりとりをしているのか
    などについてしれた。

ListenAndServeの中ではコネクションだけでなくファイルのi/oの処理っぽいのもswitchで分岐されていて、丁寧に抽象化することで統一しているんだと感じた。
TCP/IP/UDPやその他OSI標準モデルに基づく処理がされていそうで知識のなさを実感した。
勉強し直してもう一度読みたい。

参考

ryota kiseryota kise

6/3 21時〜
https://golang.org/pkg/io/
https://golang.org/pkg/context
https://blog.golang.org/context

ioとcontextを読んだ
先週いきなりnet/httpからやってしまい、他のパッケージでもよく出てくるであろうこの二つを先に読んだ方が良いと思ったので先に読む、ioだけのつもりだったが、すぐ終わったのでcontextも読んだ。

  • io.Reader io.Writerは何がうれしいのか
  • contextパッケージとはそもそも何をしているのか
  • context.Background、context.WithCancel、context.WithTimeoutなどはどういう時に使用されるのか。
     - この辺はblogに詳細に書いてあり非常にわかりやすかった。

contextに関しては全く知らないから大体見れば何がしたいかわかるぐらいにはなれたと思う、goroutineの制御などに関しては実際に触ってみないとわからない部分が多いと思うので、触っていくうちにマスターできれば良さそう。

参考

shampuくんが纏めてくれたので追記

go
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
		}
	}
}
ryota kiseryota kise

6/8 21時〜
https://golang.org/ref/spec#Index_expressions

expressions/index expressions からcomparison operator まで

参考
https://www.flyenginer.com/low/go/goのビット演算について.html

https://qiita.com/3x8tacorice/items/0b8341d7fd3ff3779111

配列操作で a[low : high : max] こんな書き方があることをしれた、自分では書かないと思うけど

func Greeting(prefix string, who ...string) の書き方は知っていたが、 Greeting("goodbye:", s...) の書き方は知らなかったので新たな発見があった。
bit演算はすることないと思っているので必要なときになったら勉強します。

ryota kiseryota kise

6/10 21時〜
https://golang.org/pkg/reflect/
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の方を指すんだと思う。

参考

ryota kiseryota kise

6/15 21時〜
https://golang.org/ref/spec#Comparison_operators

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] が出力されてよく分からなかった。
そもそもグローバルに定義されているものを引数に渡すわけでもなく更新するというこの書き方をするのが原因だと思うけど、気をつける。

参考