Tour Of Go Solutions
#Golang
I've been writing Go professionally since 2022, but have never gotten around to fully reading The Tour of Go. It's the Go to resource when it comes to getting started with Golang.
I actually learned quite a few new things that I wasn't aware of before.
Well anyway, here are my solutions.
Flow Control
https://go.dev/tour/flowcontrol/8
1package main 2 3import ( 4 "fmt" 5 "math" 6) 7 8func Sqrt(x float64) float64 { 9 z := 1.0 10 prev := -1.0 11 for i := 0; i < 10; i++ { 12 if math.Abs(z-prev) < 0.0001 { 13 break 14 } 15 prev = z 16 z -= (z*z - x) / (2 * z) 17 } 18 19 return z 20} 21 22func main() { 23 fmt.Println(Sqrt(2)) 24} 25
Slices
https://go.dev/tour/moretypes/18
1package main 2 3import "golang.org/x/tour/pic" 4 5func Pic(dx, dy int) [][]uint8 { 6 result := make([][]uint8, dy) 7 for x := range result { 8 result[x] = make([]uint8, dx) 9 for y:= range result[x] { 10 result[x][y] = uint8(x^y) 11 } 12 } 13 14 return result 15} 16 17func main() { 18 pic.Show(Pic) 19} 20
Maps
https://go.dev/tour/moretypes/23
1package main 2 3import ( 4 "golang.org/x/tour/wc" 5 "strings" 6) 7 8func WordCount(s string) map[string]int { 9 wordCounts := map[string]int{} 10 for _, word := range strings.Fields(s) { 11 wordCounts[word]++ 12 } 13 14 return wordCounts 15} 16 17func main() { 18 wc.Test(WordCount) 19} 20
Fibonacci Closure
https://go.dev/tour/moretypes/26
1package main 2 3import "fmt" 4 5func fibonacci() func() int { 6 x, y := 0, 1 7 8 return func() (z int) { 9 z, x, y = x, y, x+y 10 return 11 } 12} 13 14func main() { 15 f := fibonacci() 16 for i := 0; i < 10; i++ { 17 fmt.Println(f()) 18 } 19} 20
Stringers
https://go.dev/tour/methods/18
1package main 2 3import ( 4 "fmt" 5 "strconv" 6 "strings" 7) 8 9type IPAddr [4]byte 10 11func (ip IPAddr) String() string { 12 parts := make([]string, 0, len(ip)) 13 for _, b := range ip { 14 part := strconv.Itoa(int(b)) 15 parts = append(parts, part) 16 } 17 18 return strings.Join(parts, ".") 19} 20 21func main() { 22 hosts := map[string]IPAddr{ 23 "loopback": {127, 0, 0, 1}, 24 "googleDNS": {8, 8, 8, 8}, 25 } 26 for name, ip := range hosts { 27 fmt.Printf("%v: %v\n", name, ip) 28 } 29} 30
Errors
https://go.dev/tour/methods/20
1package main 2 3import ( 4 "fmt" 5 "math" 6) 7 8type ErrNegativeSqrt float64 9 10func (e ErrNegativeSqrt) Error() string { 11 return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e)) 12} 13 14func Sqrt(x float64) (float64, error) { 15 if x < 0 { 16 return 0, ErrNegativeSqrt(x) 17 } 18 19 z := 1.0 20 prev := -1.0 21 for i := 0; i < 10; i++ { 22 if math.Abs(z-prev) < 0.0001 { 23 break 24 } 25 prev = z 26 z -= (z*z - x) / (2 * z) 27 } 28 29 return z, nil 30} 31 32func main() { 33 fmt.Println(Sqrt(2)) 34 fmt.Println(Sqrt(-2)) 35} 36
Readers
https://go.dev/tour/methods/22
1package main 2 3import "golang.org/x/tour/reader" 4 5type MyReader struct{} 6 7func (r MyReader) Read(in []byte) (n int, err error) { 8 n = len(in) 9 for i := 0; i < n; i++ { 10 in[i] = 'A' 11 } 12 13 return n, nil 14} 15 16func main() { 17 reader.Validate(MyReader{}) 18} 19
rot13Reader
https://go.dev/tour/methods/23
1package main 2 3import ( 4 "io" 5 "os" 6 "strings" 7) 8 9type rot13Reader struct { 10 r io.Reader 11} 12 13func (r rot13Reader) Read(b []byte) (n int, err error) { 14 n, err = r.r.Read(b) 15 for i := 0; i < n; i++ { 16 if isFirstHalf(b[i]) { 17 b[i] += 13 18 } else if isSecondHalf(b[i]) { 19 b[i] -= 13 20 } 21 } 22 23 return n, err 24} 25 26func isFirstHalf(b byte) bool { 27 return (b >= 'a' && b < 'n') || (b >= 'A' && b < 'N') 28} 29 30func isSecondHalf(b byte) bool { 31 return (b >= 'n' && b <= 'z') || (b >= 'N' && b <= 'Z') 32} 33 34func main() { 35 s := strings.NewReader("Lbh penpxrq gur pbqr!") 36 r := rot13Reader{s} 37 io.Copy(os.Stdout, &r) 38} 39
Images
https://go.dev/tour/methods/25
1package main 2 3import ( 4 "golang.org/x/tour/pic" 5 "image" 6 "image/color" 7) 8 9type Image struct{ 10 Width int 11 Height int 12} 13 14func (img Image) Bounds() image.Rectangle { 15 return image.Rect(0, 0, img.Width, img.Height) 16} 17 18func (img Image) ColorModel() color.Model { 19 return color.RGBAModel 20} 21 22func (img Image) At(x, y int) color.Color { 23 v := uint8(x * y) 24 return color.RGBA{v, v, 255, 255} 25} 26 27func main() { 28 m := Image{256, 256} 29 pic.ShowImage(m) 30} 31
Equivalent Binary Trees
https://go.dev/tour/concurrency/8
1package main 2 3import ( 4 "golang.org/x/tour/tree" 5 "fmt" 6) 7 8func Walk(t *tree.Tree, ch chan int) { 9 if t == nil { 10 return 11 } 12 Walk(t.Left, ch) 13 ch <- t.Value 14 Walk(t.Right, ch) 15} 16 17func Same(t1, t2 *tree.Tree) bool { 18 chanOne, chanTwo := make(chan int), make(chan int) 19 20 go func() { 21 Walk(t1, chanOne) 22 close(chanOne) 23 }() 24 25 go func() { 26 Walk(t2, chanTwo) 27 close(chanTwo) 28 }() 29 30 for { 31 nodeOne, chanOneOpen := <-chanOne 32 nodeTwo, chanTwoOpen := <-chanTwo 33 34 if !chanOneOpen && !chanTwoOpen { 35 return true // both channels closed, trees are same 36 } 37 38 if chanOneOpen != chanTwoOpen { 39 return false // different number of nodes 40 } 41 42 if nodeOne != nodeTwo { 43 return false // different values 44 } 45 } 46} 47 48func main() { 49 fmt.Println("Trees are equivalent:", Same(tree.New(1), tree.New(1))) 50} 51
Web Crawler
https://go.dev/tour/concurrency/10
1package main 2 3import ( 4 "fmt" 5 "sync" 6) 7 8type Fetcher interface { 9 Fetch(url string) (body string, urls []string, err error) 10} 11 12type Cache struct { 13 v map[string]bool 14 mu sync.Mutex 15} 16 17func (cache *Cache) Set(key string, value bool) { 18 cache.mu.Lock() 19 cache.v[key] = value 20 cache.mu.Unlock() 21} 22 23func (cache *Cache) Get(key string) bool { 24 cache.mu.Lock() 25 defer cache.mu.Unlock() 26 return cache.v[key] 27} 28 29func Crawl(url string, depth int, fetcher Fetcher, visited *Cache, wg *sync.WaitGroup) { 30 if depth == 0 || visited.Get(url) { 31 wg.Done() 32 return 33 } 34 visited.Set(url, true) 35 36 body, urls, err := fetcher.Fetch(url) 37 if err != nil { 38 fmt.Println(err) 39 wg.Done() 40 return 41 } 42 43 fmt.Printf("found: %s %q\n", url, body) 44 45 for _, u := range urls { 46 wg.Add(1) 47 go Crawl(u, depth-1, fetcher, visited, wg) 48 } 49 wg.Done() 50} 51 52func main() { 53 visited := Cache{v: make(map[string]bool)} 54 55 var wg sync.WaitGroup 56 wg.Add(1) 57 58 Crawl("https://golang.org/", 4, fetcher, &visited, &wg) 59 60 wg.Wait() 61} 62 63type fakeFetcher map[string]*fakeResult 64 65type fakeResult struct { 66 body string 67 urls []string 68} 69 70func (f fakeFetcher) Fetch(url string) (body string, urls []string, err error) { 71 if res, ok := f[url]; ok { 72 return res.body, res.urls, nil 73 } 74 75 return "", []string{}, fmt.Errorf("not found %s", url) 76} 77 78var fetcher = fakeFetcher{ 79 "https://golang.org/": &fakeResult{ 80 "The Go Programming Language", 81 []string{ 82 "https://golang.org/pkg/", 83 "https://golang.org/cmd/", 84 }, 85 }, 86 "https://golang.org/pkg/": &fakeResult{ 87 "Packages", 88 []string{ 89 "https://golang.org/", 90 "https://golang.org/cmd/", 91 "https://golang.org/pkg/fmt/", 92 "https://golang.org/pkg/os/", 93 }, 94 }, 95 "https://golang.org/pkg/fmt/": &fakeResult{ 96 "Package fmt", 97 []string{ 98 "https://golang.org/", 99 "https://golang.org/pkg/", 100 }, 101 }, 102 "https://golang.org/pkg/os/": &fakeResult{ 103 "Package os", 104 []string{ 105 "https://golang.org/", 106 "https://golang.org/pkg/", 107 }, 108 }, 109} 110