Hero Image
More Powerful Go Execution Tracing

More Powerful Go Execution Tracing runtime/trace golang.org/x/exp/trace Flight Recording // Set up the flight recorder fr := trace.NewFlightRecorder() fr.Start() // Set up and run the HTTP server var once sync.Once http.HandleFunc("/my-endpoint", func(w http.ResponseWriter, r *http.Request) { start := time.Now() // Do some work doWork(w, r) // Got a long-running request, take a snapshot if time.Since(start) > 300*time.Millisecond { // We only do this once for simplicity; you can do it multiple times once.Do(func() { // Capture snapshot var b bytes.Buffer _, err = fr.WriteTo(&b) if err != nil { log.Print(err) return } // Write snapshot to file if err := os.WriteFile("trace.out", b.Bytes(), 0o755); err != nil { log.Print(err) return } }) } }) log.Fatal(http.ListenAndServe(":8080", nil)) Trace Reader API // Start reading trace data from stdin. r, err := trace.NewReader(os.Stdin) if err != nil { log.Fatal(err) } var blocked int var blockedOnNetwork int for { // Read event ev, err := r.ReadEvent() if err == io.EOF { break } else if err != nil { log.Fatal(err) } // Handle it if ev.Kind() == trace.EventStateTransition { st := ev.StateTransition() if st.Resource.Kind == trace.ResourceGoroutine { id := st.Resource.Goroutine() from, to := st.GoroutineTransition() // Find blocked goroutines and count them if from.Executing() && to == trace.GoWaiting { blocked++ if strings.Contains(st.Reason, "network") { blockedOnNetwork++ } } } } } // Print the values we need p := 100 * float64(blockedOnNetwork) / float64(blocked) fmt.Printf("%2.3f%% instances of goroutines blocking were to block on the network\n", p)

Hero Image
Hero Image
Take Screenshots with Selenium in Go

Take Screenshots with Selenium in Go package main import ( "fmt" log "github.com/sirupsen/logrus" "github.com/tebeka/selenium" "io/ioutil" ) const ( chromeDriverPath = "/usr/local/bin/chromedriver" port = 9515 ) func main() { var opts []selenium.ServiceOption selenium.SetDebug(false) service, err := selenium.NewChromeDriverService(chromeDriverPath, port, opts...) if err != nil { panic(err) // panic is used only as an example and is not otherwise recommended. } defer service.Stop() caps := selenium.Capabilities{"browserName": "chrome"} // Full-page screenshot // Get page width/height, resize the browser window, then take a screenshot. // Note: only headless mode allows arbitrary window sizes; otherwise the max height cannot exceed your screen resolution. // chromeCaps := chrome.Capabilities{ // Path: "", // Args: []string{ // "--headless", // }, // } // caps.AddChrome(chromeCaps) wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port)) if err != nil { panic(err) } defer wd.Quit() // ExecuteScript can run JavaScript. The return value is interface{}, so assert to float then convert to int. // height, _ := wd.ExecuteScript("return document.body.parentNode.scrollHeight", nil) // var realHeight = int(height.(float64)) // Then set the window size. // wd.ResizeWindow("", 1920, realHeight) if err := wd.Get("https://github.com/tgbot-collection/archiver"); err != nil { panic(err) } screenshot, err := wd.Screenshot() if err != nil { log.Errorln(err) } ioutil.WriteFile("screenshot.png", screenshot, 0644) } Full-page screenshot Get the page width/height, resize the browser window accordingly, and then take the screenshot. Note that only headless mode allows arbitrary window sizes; otherwise the maximum height cannot exceed your display resolution.

Hero Image
Use Go Fuzzing to Write More Complete Unit Tests

Use Go Fuzzing to Write More Complete Unit Tests func Pow(base uint, exponent uint) uint { if exponent == 0 { return 1 } return base * Pow(base, exponent-1) } func FuzzPow(f *testing.F) { f.Fuzz(func(t *testing.T, x, y uint) { assert := assert.New(t) assert.Equal(Pow(x, 0), uint(1)) assert.Equal(Pow(x, 1), x) assert.Equal(Pow(x, 2), x*x) if x > 0 && y > 0 { assert.Equal(Pow(x, y)/x, Pow(x, y-1)) } }) } go test -fuzz=Fuzz -fuzztime 20s When a fuzz test fails, Go records the input in testcase/ You will find that when x=6 and y=30, the assert fails, i.e., pow(6, 30)/6 is not equal to pow(6, 29). That seems odd, but after testing you will see it is because pow(6, 30) overflows. The max.MaxUint in Go is about 18 * 10^¹⁸, while 6^²⁹ is about 7 * 10^¹⁸. If you multiply 6^²⁹ by 6, it overflows and yields 8 * 10^¹⁸. It is like running two laps and ending up near the starting point. var ErrOverflow = fmt.Errorf("overflow") func Pow(base uint, exponent uint) (uint, error) { if exponent == 0 { return 1 } prevResult, err := Pow(base, exponent-1) if math.MaxUint/base < prevResult { return 0, ErrOverflow } return base * prevResult, nil } func FuzzPow(f *testing.F) { f.Fuzz(func(t *testing.T, x, y uint) { assert := assert.New(t) if result, err := Pow(x, 1); err != ErrOverflow { assert.Equal(result, x) } if result, err := Pow(x, y); x > 0 && y > 0 && err != ErrOverflow { resultDivX, _ := Pow(x, y-1) assert.Equal(result/x, resultDivX) } }) }