I finished the official Grammar teaching of A Tour of Go in these two days, with A lot of Excercise. Hope to be useful to you, if other people have also written, and think I write wrong, ask for advice! ❤ ️
Exercise: Loops and Functions
The title
- Give me a number
x
, we use loop and function to find the square rootz
, i.e.,Z squared = x
- Tour.golang.org/flowcontrol…
answer
package main
import (
"fmt"
"math"
)
func Sqrt(x float64) float64 {
z := x/2
for i:= 0; math.Abs(z*z - x) > 0.0000000001; i++ {
z -= (z*z - x) / (2*z)
fmt.Println(i, "z:", z, "z^2 -x:", z*z - x)
}
return z
}
func main(a) {
fmt.Println(Sqrt(1000))}Copy the code
z := x/2
The hint is set to 1.Math.Abs(z* z-x) > 0.0000000001
Using the logic of optimal solution is to give a tolerance0.0000000001
That’s what we figured out using the formulaZ squared
与x
The difference is small enough that we assume the estimatedz
It’s an approximate accurate value.
Exercise: Slices
The title
- Write a
Pic
Function to generate one[][]uint8
Array of Array. Its size is determined by the parameter(dx, dy int)
Decision, this one hasdy
Each of these arrays has a length ofdx
The array. And the relative positionpic[y][x]
Is the Bluescale (only blue) value for this image in the format ofuint8
. - Tour.golang.org/moretypes/1…
answer
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int)[] []uint8 {
pic := make([] []uint8, dy)
for i := range pic {
pic[i] = make([]uint8, dx)
for j := range pic[i] {
pic[i][j] = uint8(i*j + j*j)
}
}
return pic
}
func main(a) {
pic.Show(Pic)
}
Copy the code
pic := make([][]uint8, dy)
I’m going to create an array of lengthdy
The contents of each element in an array are an array[]uint8
pic[i] = make([]uint8, dx)
At the first point in the arrayi
Let’s create another one[]uint8
Array of lengthdx
pic[i][j] = uint8(i*j + j*j)
Denotes that in the Calculation formula of the Bluesacle we designed,pic[i][j]
The value of the position is zerouint8(i*j + j*j)
(Here you can arbitrarily change a few, you can see a lot of different effects!)
Exercise: Maps
The title
- Implement a function
WordCount
, it can reply to onemap
This contains the number of occurrences of the word word in the input string. - For example: “I love you you you you”, return
map[string]int{"I":1, "love":1, "you":3}
- Tour.golang.org/moretypes/2…
answer
package main
import (
"golang.org/x/tour/wc"
"strings"
)
func WordCount(s string) map[string]int {
m := make(map[string]int)
words := strings.Fields(s)
for _, word := range words {
m[word] = m[word] + 1
}
return m
}
func main(a) {
wc.Test(WordCount)
}
Copy the code
- Strings.Files(s) this function automatically splits a string into an array, each of which contains a word
- To establish
map
And then every time in the arrayword
If it appears, it increases by 1
Exercise: Fibonacci closure
The title
- To implement a
fibonacci
Function to return a function - This function will continuously output the Fibonacci sequence
- Tour.golang.org/moretypes/2…
answer
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci(a) func(a) int {
a, b := 0.1
return func(a) int {
c := a
a, b = b, a+b
return c
}
}
func main(a) {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Copy the code
- A closure, also called a closure, means that a variable that needs to be used in a function is defined outside the function itself
- In the above
func fibonacci() func() int
, returns a functionfunc() int
And this function returns one at a timeint
- in
fibonacci()
The variablea
和b
Defined in a functionfibonacci()
Is returned by this functionreturn func() int { ... }
The function is referred to, that is, in the function that is returneda
和b
Both variables are always stored in memory, and their values are always changing f := fibonacci()
中f
是fibonacci()
The function that returns, in the initial case, at this pointa, b := 0, 1
- For the first time
f()
Call as an example:c := a
:c
The assignment fora
Namely 0a, b = b, a+b
:a
The assignment forb
Which is 1,b
The assignment fora+b
Which is 1return c
Returns 0, which is the Fibonacci numberThe first value
- The second time
f()
Call, notice at this pointa
Is 1,b
Is 1:c := a
:c
The assignment fora
Which is 1a, b = b, a+b
:a
The assignment forb
Which is 1,b
The assignment fora+b
That is 2return c
Returns 1, which is the Fibonacci sequenceThe second value
- And so on
f
The function is called 10 times and outputs the first 10 values of the Fibonacci sequence
Exercise: Stringers
The title
- for
type IPAddr [4]byte
Add Stringer Interface function to output string, i.eIPAddr{1, 2, 3, 4}
The print is2.
- tour.golang.org/methods/18
answer
package main
import (
"fmt"
"strings"
"strconv"
)
type IPAddr [4]byte
// TODO: Add a "String() string" method to IPAddr.
func (ip IPAddr) String(a) string {
s := make([]string.len(ip))
for i, val := range ip {
s[i] = strconv.Itoa(int(val))
}
return fmt.Sprintf(strings.Join(s, "."))}func main(a) {
hosts := map[string]IPAddr{
"loopback": {127.0.0.1},
"googleDNS": {8.8.8.8}},for name, ip := range hosts {
fmt.Printf("%v: %v\n", name, ip)
}
}
Copy the code
- Strconv. Itoa int to String
IPAddr
It’s a size 4[]byte
, we generate one[4]string
An array ofs
Each element is a bit in the IP address, and we usestrconv.Itoa(int(val))
Convert it to a stringstrings.Join(s, ".")
Use string arrays"."
together- In this way
fmt.Printf("%v: %v\n", name, ip)
, totype IPAddr
Call it by defaultStringer interface
The definition ofString()
Function to output
Exercise: Errors
The title
- Exercise: Loops and Functions
sqrt
Function, added when the argument is a negative numbertype ErrNegativeSqrt float64
And by definitionfunc (e ErrNegativeSqrt) Error() string
So that makes it zeroerror
- tour.golang.org/methods/20
answer
package main
import (
"fmt"
"math"
)
type ErrNegativeSqrt float64
func (e ErrNegativeSqrt) Error(a) string {
return fmt.Sprintf("cannot Sqrt negative number: %v".float64(e))
}
func Sqrt(x float64) (float64, error) {
if (x > 0) {
z:= x/2
for i:= 0; math.Abs(z*z - x) > 0.0000000001; i++ {
z -= (z*z - x) / (2*z)
fmt.Println(i, "z:", z, "z^2 -x:", z*z - x)
}
return z, nil
} else {
return 0, ErrNegativeSqrt(x)
}
}
Copy the code
error
The type is a built-in interface that needs to be definedError() string
Function, test oneerror
If the type isnil
Is a way to define whether a function returns an error. Such as:i, err := strconv.Atoi("42")
The return value ofi
Represents the return value of the function, anderr
If it is notnil
If so, an error has occurredfunc (e ErrNegativeSqrt) Error() string
Defines theErrNegativeSqrt
Belong toerror
的Error()
Delta function, which is just a neat statementErrNegativeSqrt
Is aerror
func Sqrt(x float64) (float64, error)
The function returns two values, the square root of the argument and the seconderror
When the latter is notnil
At the time ofPrintln
Is automatically calledError()
Output the corresponding error message string.
Exercise: Readers
The title
- To implement a
Reader
Type to output an infinite number'A'
The character of the flow - tour.golang.org/methods/22
answer
package main
import (
"fmt"
"golang.org/x/tour/reader"
)
type MyReader struct{}
type ErrEmptyBuffer []byte
func (b ErrEmptyBuffer) Error(a) string {
return fmt.Sprintf("cannot read an empty buffer: %v", b)
}
// TODO: Add a Read([]byte) (int, error) method to MyReader.
func (reader MyReader) Read(b []byte) (int, error) {
bLength := len(b)
if (bLength == 0) {
return 0, ErrEmptyBuffer(b)
}
for i := range b {
b[i] = 'A'
}
return bLength, nil
}
func main(a) {
reader.Validate(MyReader{})
}
Copy the code
- because
MyReader
It prints an infinite number'A'
, so just enter parametersb []byte
If it’s not an empty Buffer, it’s full - when
bLength == 0
Is the Bufferb
If null, returnErrEmptyBuffer(b)
error - Everything that is not empty is filled
'A'
And returnbLength, nil
Exercise: rot13Reader
The title
- To implement a
rot13Reader
Type causes it to contain oneio.Reader
Make it workRead
Function, automatically based onrot13
To convert the corresponding alphabetic characters. - tour.golang.org/methods/23
answer
package main
import (
"io"
"os"
"strings"
)
type rot13Reader struct {
r io.Reader
}
func rot13(c byte) byte {
switch {
case (c >= 'A' && c <= 'M') || (c >= 'a' && c <= 'm'):
c += 13
case (c >= 'N' && c <= 'Z') || (c >= 'n' && c <= 'z'):
c -= 13
}
return c
}
func (reader *rot13Reader) Read(b []byte) (n int, err error) {
n, err := reader.r.Read(b)
for i := range b {
b[i] = rot13(b[i])
}
return n, err
}
func main(a) {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}
Copy the code
- According to the first
rot13
Rule implementation functionfunc rot13(c byte) byte
, that is,A-M
与N-Z
Exchange, anda-m
与n-z
The conversion of - define
rot13Reader
的Read
Function, which is included in the first use periodr
Reader to read the data, and then each piece of data passes throughrot13
Convert, and eventually return the corresponding numeric result
Exercise: Images
The title
- Optimize the image functions implemented in Exercise: Slices, one this time
image.Image
The image is not just a two-dimensional array of data - To define a
Image
Type and define the correspondingimage.Image
Interface,ColorModel
usecolor.RGBAModel
Bounds
useimage.Rectangle
The type andimage.Rect(0, 0, w, h)
defineAt
Returns the color on the pixel of the specific image, and finally usescolor.RGBA{v, v, 255, 255}
define
- tour.golang.org/methods/25
answer
package main
import (
"golang.org/x/tour/pic"
"image"
"image/color"
)
type Image struct{
W int
H int
}
func (i Image) ColorModel(a) color.Model {
return color.RGBAModel
}
func (i Image) Bounds(a) image.Rectangle {
return image.Rect(0.0, i.W, i.H)
}
func (i Image) At(x, y int) color.Color {
v := uint8(x*y + y*y)
return color.RGBA{v, v, 255.255}}func main(a) {
m := Image{200.200}
pic.ShowImage(m)
}
Copy the code
- Because I’m gonna use
image.Rect
.color.RGBAModel
.color.RGBA
So let’s introduce"image"
和"image/color"
packages - You define the correlation function, and you get the result, right here
At
Function I use the previous picture color calculation formulav := uint8(x*y + y*y)
Exercise: Equivalent Binary Trees
The title
- The same binary tree sequence may be stored in different binary trees. For example, in the figure above, two binary trees store the sequence 1, 1, 2, 3, 5, 8, 13. define
Tree
Type and implement the following function to test bothTree
Whether to store the same array.- implementation
Tree
的Walk
Method, which passes in the sequence of numbers stored in the tree one by onech chan int
Student: Middle, which is equal tofunc Walk(t *tree.Tree, ch chan int)
And this is done in goroutinego Walk(tree.New(1), ch)
. Note:tree.New(k)
It randomly generates a tree of different structures, but it all stores the same arrayk
.2k
. .10k
. - implementation
Same
Function and callWalk
Method to make it possible to compare twoTree
Whether to store the same array. Such as:Same(tree.New(1), tree.New(1))
Should be returnedtrue
Because it’s all there1
.2
.10
. whileSame(tree.New(1), tree.New(2))
Should be returnedfalse
- implementation
answer
package main
import (
"fmt"
"golang.org/x/tour/tree"
)
// type Tree struct {
// Left *Tree
// Value int
// Right *Tree
// }
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
ift.Left ! =nil {
Walk(t.Left, ch)
}
ch <- t.Value
ift.Right ! =nil {
Walk(t.Right, ch)
}
}
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
var v1, v2 int
c1 := make(chan int)
c2 := make(chan int)
go Walk(t1, c1)
go Walk(t2, c2)
for i := 0; i < 10; i++ {
v1 = <-c1
v2 = <-c2
ifv1 ! = v2 {return false}}return true
}
func main(a) {
ch := make(chan int)
go Walk(tree.New(10), ch)
for i := 0; i < 10; i++ {
fmt.Println(<-ch)
}
fmt.Println(Same(tree.New(1), tree.New(1)))}Copy the code
Walk
In the method, we follow thet.Left
.ch <- t.Value
.t.Right
Pass in the data one by one in orderch
Same
Method, because we know thattree.New(k)
The generated tree contains 10 nodes, so we generate two Channels to store two respectivelyTree
在Walk
And then a Loop of 10 times takes out a value from it each time to compare whether the value under the corresponding sequence is the same. If there are differences, the two trees are not the same.
Exercise: Web Crawler
Ymkalasoo, we are looking for a good Go developer
The title
- Implementation of a parallel Web Crawler, implementation
Crawl
Function makes it possible to catch them in parallelURL
But don’t repeat fetching fakeFetcher
Is a dummy data set representing data that can be captured by the crawler under test- Tour.golang.org/concurrency…
answer
package main
import (
"fmt"
"sync"
)
type Fetcher interface {
// Fetch returns the body of URL and
// a slice of URLs found on that page.
Fetch(url string) (body string, urls []string, err error)
}
type UrlChecker struct {
urls map[string]bool
mux sync.Mutex
}
func (c *UrlChecker) Crawled(url string) bool {
c.mux.Lock()
if c.urls[url] {
defer c.mux.Unlock()
return true
}
c.urls[url] = true
defer c.mux.Unlock()
return false
}
var uc = UrlChecker{urls: make(map[string]bool)}
// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher, ret chan string) {
// TODO: Fetch URLs in parallel.
// TODO: Don't fetch the same URL twice.
// This implementation doesn't do either:
defer close(ret)
if depth <= 0 {
return
}
if uc.Crawled(url) {
return
}
body, urls, err := fetcher.Fetch(url)
iferr ! =nil {
fmt.Println(err)
return
}
ret <- fmt.Sprintf("found: %s %q\n", url, body)
results := make([]chan string.len(urls))
for i, u := range urls {
results[i] = make(chan string)
go Crawl(u, depth- 1, fetcher, results[i])
}
for _, result := range results {
for s := range result {
ret <- s
}
}
return
}
func main(a) {
result := make(chan string)
go Crawl("https://golang.org/".4, fetcher, result)
for s := range result {
fmt.Println(s)
}
}
// fakeFetcher is Fetcher that returns canned results.
type fakeFetcher map[string]*fakeResult
type fakeResult struct {
body string
urls []string
}
func (f fakeFetcher) Fetch(url string) (stringAnd []string, error) {
if res, ok := f[url]; ok {
return res.body, res.urls, nil
}
return "".nil, fmt.Errorf("not found: %s", url)
}
// fetcher is a populated fakeFetcher.
var fetcher = fakeFetcher{
"https://golang.org/": &fakeResult{
"The Go Programming Language"And []string{
"https://golang.org/pkg/"."https://golang.org/cmd/",}},"https://golang.org/pkg/": &fakeResult{
"Packages"And []string{
"https://golang.org/"."https://golang.org/cmd/"."https://golang.org/pkg/fmt/"."https://golang.org/pkg/os/",}},"https://golang.org/pkg/fmt/": &fakeResult{
"Package fmt"And []string{
"https://golang.org/"."https://golang.org/pkg/",}},"https://golang.org/pkg/os/": &fakeResult{
"Package os"And []string{
"https://golang.org/"."https://golang.org/pkg/",,}}}Copy the code
UrlChecker
It was to test aurl
Have you beenfetch
Yes, it contains oneurls map[string]bool
Store URL fetching, andmux sync.Mutex
To prevent the data from being modified repeatedly so that it doesn’t show up when fetcher is parallel, because none of the urls are thereUrlChecker
Tagged fetch, and then fetch simultaneously.func (c *UrlChecker) Crawled(url string) bool
To store the state of a URL that has been fetched. During testingc.mux.Lock()
If so, this section of data is blocked from being modified by other Goroutine.defer c.mux.Unlock()
Mean inreturn
Then perform the Mutual Exclusion lock unlocks.- The statement
var uc = UrlChecker{urls: make(map[string]bool)}
whenuc.Crawled(url)
是true
When, no longer grab the corresponding URL. func Crawl(url string, depth int, fetcher Fetcher, ret chan string)
The last parameterret chan string
Pass in a channel to store the fetch resultsresults := make([]chan string, len(urls))
For each url that needs to be captured at a deeper level, multiple channels are generated and captured one by onego Crawl(u, depth-1, fetcher, results[i])
Cyclic fetch of urls-
Copy the code
For _, result := range results {for s := range result {ret < -s}} ‘ ‘ Complete all fetching
Final output:
not found: https://golang.org/cmd/
found: https://golang.org/ "The Go Programming Language"
found: https://golang.org/pkg/ "Packages"
found: https://golang.org/pkg/fmt/ "Package fmt"
found: https://golang.org/pkg/os/ "Package os"
Copy the code
Hard, I also learn to Go oh!