type clientConfig struct { // Number of worker goroutines publishing log events Workers int`config:"workers" validate:"min=1"` // Max number of events in a batch to send to a single client BatchSize int`config:"batch_size" validate:"min=1"` // Max number of retries for single batch of events RetryLimit int`config:"retry_limit"` // Schema WebSocket Schema Schema string`config:"schema"` // Addr WebSocket Addr Addr string`config:"addr"` // Path WebSocket Path Path string`config:"path"` // PingInterval WebSocket PingInterval PingInterval int`config:"ping_interval"` }
funcmain() { // src is the input that we want to tokenize. src, _ := ioutil.ReadFile(`main.go`)
// Initialize the scanner var s scanner.Scanner // positions are relative to fSet fSet := token.NewFileSet() file := fSet.AddFile("", fSet.Base(), len(src)) // nil means no error handler s.Init(file, src, nil, scanner.ScanComments)
// Repeated calls to Scan yield the token sequence found in the input for { pos, tok, lit := s.Scan() if tok == token.EOF { break } fmt.Printf("%s\t%s\t%q\n", fSet.Position(pos), tok, lit) } }
GOSSAFUNC=main go tool compile main.go && open ssa.html
SSA阶段
SSA优化解析
start Tab上生成了最开始的SSA
变量 a 和 b 与 if 条件一起在此处突出显示,以便我们稍后查看这些行是如何更改的。 代码还向我们展示了编译器如何管理 println 函数,它被分解为 4 个步骤:printlock、printint、printnl、printunlock。 编译器会自动为我们加锁,并根据参数的类型调用相关方法正确打印。 在我们的示例中,由于 a 和 b 在编译时已知,编译器可以计算最终结果并将变量标记为不再需要。 opt阶段 会优化这部分:
Programs using times should typically store and pass them as values, not pointers. That is, time variables and struct fields should be of type time.Time, not *time.Time. A Time value can be used by multiple goroutines simultaneously.
funcTestSize(t *testing.T) { { var x byte = 0 fmt.Println("byte size is ", unsafe.Sizeof(x)) } { var x int32 = 0 fmt.Println("int32 size is ", unsafe.Sizeof(x)) } { var x int = 0 fmt.Println("int size is ", unsafe.Sizeof(x)) } { var x int64 = 0 fmt.Println("int64 size is ", unsafe.Sizeof(x)) } { var x float32 = 0 fmt.Println("float32 size is ", unsafe.Sizeof(x)) } { var x float64 = 0 fmt.Println("float64 size is ", unsafe.Sizeof(x)) } { t := time.Now() fmt.Println("time size is ", unsafe.Sizeof(t)) } }
const ( // 6 bits to represent a letter index letterIdBits = 6 // All 1-bits as many as letterIdBits letterIdMask = 1<<letterIdBits - 1 letterIdMax = 63 / letterIdBits )
funcrandStr(n int)string { b := make([]byte, n) // A rand.Int63() generates 63 random bits, enough for letterIdMax letters! for i, cache, remain := n-1, rand.Int63(), letterIdMax; i >= 0; { if remain == 0 { cache, remain = rand.Int63(), letterIdMax } if idx := int(cache & letterIdMask); idx < len(letters) { b[i] = letters[idx] i-- } cache >>= letterIdBits remain-- } returnstring(b) }
const ( // 6 bits to represent a letter index letterIdBits = 6 // All 1-bits as many as letterIdBits letterIdMask = 1<<letterIdBits - 1 letterIdMax = 63 / letterIdBits )
funcrandStr(n int)string { b := make([]byte, n) // A rand.Int63() generates 63 random bits, enough for letterIdMax letters! for i, cache, remain := n-1, src.Int63(), letterIdMax; i >= 0; { if remain == 0 { cache, remain = src.Int63(), letterIdMax } if idx := int(cache & letterIdMask); idx < len(letters) { b[i] = letters[idx] i-- } cache >>= letterIdBits remain-- } returnstring(b) }