Solution 4: Building Web Services
Let’s solve the challenge set in the previous lesson.
We'll cover the following...
We'll cover the following...
Solution
Here’s a simple implementation of ab(1) using goroutines and channels in Go.
To run the server side of the ab(1) utility, open a new terminal window and copy and paste the following command into the terminal:
python3 -m http.server 8082
To run the client side, copy and paste the following command into the other terminal window:
go run ab.go -url http://localhost:8082 -c 5 -n 10
Execute the server and client sides in the following playground:
package main
import (
	"flag"
	"fmt"
	"net/http"
	"sync"
	"io"
	"time"
)
func main() {
	// Parse command line flags
	var (
		concurrency int
		requests    int
		url         string
	)
	flag.IntVar(&concurrency, "c", 1, "Number of multiple requests to make at a time")
	flag.IntVar(&requests, "n", 1, "Number of requests to perform")
	flag.StringVar(&url, "url", "", "URL to test")
	flag.Parse()
	if url == "" {
		fmt.Println("Error: URL is required")
		return
	}
	// Create a channel to track completed requests
	done := make(chan bool)
	// Create a wait group to synchronize goroutines
	var wg sync.WaitGroup
	// Start timing the requests
	start := time.Now()
	// Launch the requested number of goroutines
	for i := 0; i < requests; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			// Make the HTTP request
			resp, err := http.Get(url)
			if err != nil {
				fmt.Println("Error making request:", err)
				return
			}
			defer resp.Body.Close()
			// Read the response body to completion to simulate a real-world scenario
			_, _ = io.ReadAll(resp.Body)
			// Notify that the request is done
			done <- true
		}()
		// Limit the concurrency
		if i%concurrency == 0 {
			time.Sleep(time.Millisecond * 10)
		}
	}
	// Calculate and print the results
	duration := time.Since(start)
	reqsPerSec := float64(requests) / duration.Seconds()
	fmt.Println("Concurrency Level: %d\n", concurrency)
	fmt.Printf("Time taken for tests: %v seconds\n", duration.Seconds())
	fmt.Printf("Complete requests: %d\n", requests)
	fmt.Printf("Requests per second: %.2f [#/sec]\n", reqsPerSec)
}
ab.go
Code explanation
- Lines 3–9: These are the package imports. The - flagpackage provides a ...