Go Playground exercise

关于

最近刚开始接触Go语言,这里做一些记录,这不是一篇介绍Go语言特性的文章,也不是讲述实际应用的文章。

 

前言:

Go语言,作为Better C,目前适用领域多是在高并发的BE程序。成熟的产品有Docker(现在改名为Moby)等。设计思想上相比Cpp做加法,它是作减法。在整合新的语言特性基础上,改良了C一些不易理解的地方。作为静态语言,效率自不用说,可以方便地调用C的库。同时因为简洁的语法,开发效率很高。

 

Playground

 

https://tour.golang.org/moretypes/18

 

Exercise: Slices

Implement Pic. It should return a slice of length dy, each element of which is a slice of dx 8-bit unsigned integers. When you run the program, it will display your picture, interpreting the integers as grayscale (well, bluescale) values.

The choice of image is up to you. Interesting functions include (x+y)/2x*y, and x^y.

(You need to use a loop to allocate each []uint8 inside the [][]uint8.)

(Use uint8(intValue) to convert between types.)

 

这里尽量把之前学到的特性都用上

 1 package main
 2 
 3 import "golang.org/x/tour/pic"
 4 
 5 func Pic(dx, dy int) [][]uint8 {
 6     local := make([][]uint8,0,0)
 7     for i:=0;i<dy;i++{
 8         local=append(local,make([]uint8,dx))
 9     }
10     for i,_:= range local{
11         for j,_ :=range local[i]{
12             local[i][j]=uint8((i+j)/2)
13         }
14     }
15     return local
16 }
17 
18 func main() {
19     pic.Show(Pic)
20 }
View Code

这里一开始用local := make([][]uint8,dy)遇到一个out of range的panic,可能是测试脚本调用返回的二维数组取值时越界了。

这个语句已经生成了dy个空的类型为[]uint8的元素,之后只能用for循环依次赋值,而直接用append会在dy个元素之后再累加dy个一维数组。

 

 

 

https://tour.golang.org/moretypes/23

Exercise: Maps

Implement WordCount. It should return a map of the counts of each “word” in the string s. The wc.Test function runs a test suite against the provided function and prints success or failure.

You might find strings.Fields helpful.

 

 1 package main
 2 
 3 import (
 4     "golang.org/x/tour/wc"
 5     "strings"
 6 )
 7 
 8 func WordCount(s string) map[string]int {
 9     stringArr:=strings.Fields(s)
10     localMap :=make(map[string]int)
11     for _,value:=range stringArr{
12         _,ok:=localMap[value]
13         if ok {
14             localMap[value]++
15         }else{
16             localMap[value]=1
17         }
18     }
19     return localMap//map[string]int{"x": 1}
20 }
21 
22 func main() {
23     wc.Test(WordCount)
24 }
View Code

 不同于c++,这里用下标运算符查询元素并不会插入元素,所以可以安全作find查询,go语言的逻辑语句左花括号必须在同一行

 

 

 

https://tour.golang.org/moretypes/26

Exercise: Fibonacci closure

Let's have some fun with functions.

Implement a fibonacci function that returns a function (a closure) that returns successive fibonacci numbers (0, 1, 1, 2, 3, 5, ...).

 

 1 package main
 2 
 3 import "fmt"
 4 
 5 // fibonacci is a function that returns
 6 // a function that returns an int.
 7 func fibonacci() func() int {
 8     before1:=0
 9     before2:=1
10     count:=0
11     return func() int {  
12         if(count==0){
13             count++
14             return 0
15         }
16         if(count==1){
17             count++
18             return 1
19         }
20         before1,before2=before2,before1+before2
21         return before2
22     }
23 }
24 
25 func main() {
26     f := fibonacci()
27     for i := 0; i < 10; i++ {
28         fmt.Println(f())
29     }
30 }
View Code

这里是用闭包来实现斐波那契数列,应该还可以简化一些,赋值预算语句左右似乎并不指向同一对象,可以把右侧当做一个副本

 

https://tour.golang.org/methods/18

 

Exercise: Stringers

 

Make the IPAddr type implement fmt.Stringer to print the address as a dotted quad.

 

For instance, IPAddr{1, 2, 3, 4} should print as "1.2.3.4".

 

 

 

 1 package main
 2 
 3 import ( 
 4     "fmt"
 5     "strconv"
 6     "strings"
 7 )
 8 
 9 type IPAddr [4]byte
10 
11 // TODO: Add a "String() string" method to IPAddr.
12 func (ip IPAddr) String() string{
13     s:=make([]string,len(ip))
14     for i:=range ip{
15         s[i] = strconv.Itoa(int(ip[i]))    
16     }
17     return strings.Join(s,".")
18 }
19 func main() {
20     hosts := map[string]IPAddr{
21         "loopback":  {127, 0, 0, 1},
22         "googleDNS": {8, 8, 8, 8},
23     }
24     for name, ip := range hosts {
25         fmt.Printf("%v: %v\n", name, ip)
26     }
27 }
View Code

 

 

https://tour.golang.org/flowcontrol/8

Exercise: Loops and Functions

As a way to play with functions and loops, let's implement a square root function: given a number x, we want to find the number z for which z² is most nearly x.

Computers typically compute the square root of x using a loop. Starting with some guess z, we can adjust z based on how close z² is to x, producing a better guess:

z -= (z*z - x) / (2*z)

Repeating this adjustment makes the guess better and better until we reach an answer that is as close to the actual square root as can be.

Implement this in the func Sqrt provided. A decent starting guess for z is 1, no matter what the input. To begin with, repeat the calculation 10 times and print each z along the way. See how close you get to the answer for various values of x (1, 2, 3, ...) and how quickly the guess improves.

Hint: To declare and initialize a floating point value, give it floating point syntax or use a conversion:

z := 1.0
z := float64(1)

Next, change the loop condition to stop once the value has stopped changing (or only changes by a very small amount). See if that's more or fewer than 10 iterations. Try other initial guesses for z, like x, or x/2. How close are your function's results to the math.Sqrt in the standard library?

(Note: If you are interested in the details of the algorithm, the z² − x above is how far away z² is from where it needs to be (x), and the division by 2z is the derivative of z², to scale how much we adjust z by how quickly z² is changing. This general approach is called Newton's method. It works well for many functions but especially well for square root.)

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 var(
 8     z = float64(1)
 9     )
10 func Sqrt(x float64) float64 {
11     for i,z := 0,float64(1);i<100;i++ {
12         z-=(z*z-x)/2*z
13         fmt.Println(z);
14     }
15     return 0
16 }
17 
18 func main() {
19     fmt.Println(Sqrt(2))
20 }
View Code

 

https://tour.golang.org/methods/20

 

Exercise: Errors

Copy your Sqrt function from the earlier exercise and modify it to return an error value.

Sqrt should return a non-nil error value when given a negative number, as it doesn't support complex numbers.

Create a new type

type ErrNegativeSqrt float64

and make it an error by giving it a

func (e ErrNegativeSqrt) Error() string

method such that ErrNegativeSqrt(-2).Error() returns "cannot Sqrt negative number: -2".

Note: a call to fmt.Sprint(e) inside the Error method will send the program into an infinite loop. You can avoid this by converting e first: fmt.Sprint(float64(e)). Why?

Change your Sqrt function to return an ErrNegativeSqrt value when given a negative number.

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 type ErrNegativeSqrt float64
 8 
 9 func (e ErrNegativeSqrt) Error() string {
10     return fmt.Sprint("cannot Sqrt negative number: ", float64(e)) //infinite call error?
11 }
12 
13 func Sqrt(x float64) (float64, error) {
14     if x < 0 {
15         return 0, ErrNegativeSqrt(x)
16     }
17 
18     for i, z := 0, float64(1); i < 100; i++ {
19         z -= (z*z - x) / 2 * z
20         fmt.Println(z)
21     }
22     return 0, nil
23 }
24 
25 func main() {
26     if _, err := Sqrt(2); err != nil {
27         fmt.Println(err)
28     }
29     if _, err := Sqrt(-2); err != nil {
30         fmt.Println(err)
31     }
32     //fmt.Println(Sqrt(2))
33     //fmt.Println(Sqrt(-2))
34 }
View Code

 

https://tour.golang.org/methods/22

Exercise: Readers

Implement a Reader type that emits an infinite stream of the ASCII character 'A'.

 1 package main
 2 
 3 import (
 4     "golang.org/x/tour/reader"
 5 )
 6 
 7 type MyReader struct{}
 8 
 9 // TODO: Add a Read([]byte) (int, error) method to MyReader.
10 func (reader MyReader) Read(b []byte) (int, error) {
11     for i:=range b{
12         b[i] = 65
13     }
14     return len(b),nil
15 }
16 func main() {
17     reader.Validate(MyReader{})
18 }
View Code

 

 

https://tour.golang.org/methods/23

Exercise: rot13Reader

A common pattern is an io.Reader that wraps another io.Reader, modifying the stream in some way.

For example, the gzip.NewReader function takes an io.Reader (a stream of compressed data) and returns a *gzip.Readerthat also implements io.Reader (a stream of the decompressed data).

Implement a rot13Reader that implements io.Reader and reads from an io.Reader, modifying the stream by applying the rot13 substitution cipher to all alphabetical characters.

The rot13Reader type is provided for you. Make it an io.Reader by implementing its Read method.

 1 package main
 2 
 3 import (
 4     "io"
 5     "os"
 6     "strings"
 7 )
 8 
 9 type rot13Reader struct {
10     r io.Reader
11 }
12 
13 func (reader rot13Reader) Read(b []byte) (int, error) {
14     ret,err:=reader.r.Read(b)
15     return ret,err
16 }
17 
18 func main() {
19     s := strings.NewReader("Lbh penpxrq gur pbqr!")
20     r := rot13Reader{s}
21     io.Copy(os.Stdout, &r)
22 }
View Code

 

https://tour.golang.org/methods/25

Exercise: Images

Remember the picture generator you wrote earlier? Let's write another one, but this time it will return an implementation of image.Image instead of a slice of data.

Define your own Image type, implement the necessary methods, and call pic.ShowImage.

Bounds should return a image.Rectangle, like image.Rect(0, 0, w, h).

ColorModel should return color.RGBAModel.

At should return a color; the value v in the last picture generator corresponds to color.RGBA{v, v, 255, 255} in this one.

 1 package main
 2 
 3 import (
 4     "golang.org/x/tour/pic"
 5     "image"
 6     "image/color"
 7 )
 8 
 9 type Image struct{
10     x int
11     y int
12     w int
13     h int
14     r uint8
15     g uint8
16     b uint8
17     a uint8
18 }
19 
20 func (img Image) ColorModel() color.Model{
21     return color.RGBAModel
22 }
23 func (img Image) Bounds() image.Rectangle{
24     return image.Rect(img.x,img.y,img.w,img.h)
25 }
26 func (img Image) At(x, y int) color.Color{
27     return color.RGBA{img.r,img.g,img.b,img.a}
28 }
29 func main() {
30     m := Image{0,0,200,200,20,50,30,128}
31     pic.ShowImage(m)
32 }
View Code

 

 

https://tour.golang.org/concurrency/7

Exercise: Equivalent Binary Trees

 1 package main
 2 
 3 import (
 4     "golang.org/x/tour/tree"
 5     "fmt"
 6 )
 7 
 8 // Walk walks the tree t sending all values
 9 // from the tree to the channel ch.
10 func Walk(t *tree.Tree, ch chan int){
11     if t!=nil{
12         if t.Left != nil{
13             Walk(t.Left,ch)
14         }
15         ch<-t.Value
16         if t.Right !=nil{
17             Walk(t.Right,ch)
18         }
19     }
20 }
21 
22 // Same determines whether the trees
23 // t1 and t2 contain the same values.
24 func Same(t1, t2 *tree.Tree) bool{
25     ch1:=make(chan int)
26     ch2:=make(chan int)
27     go Walk(t1,ch1)
28     go Walk(t2,ch2)
29     for i:=0;i<10;i++{
30         if (<-ch1) != (<-ch2){
31             return false    
32         }
33     }
34     return true
35 }
36 
37 func main() {
38     ch:=make(chan int)
39     go Walk(tree.New(1),ch)
40     for i:=0;i<10;i++{
41         fmt.Println(<-ch)    
42     }
43     
44     fmt.Printf("is tree.New(1) equal with tree.New(1)?%v\n",Same(tree.New(1),tree.New(1)))
45     fmt.Printf("is tree.New(1) equal with tree.New(2)?%v\n",Same(tree.New(1),tree.New(2)))
46 }

这里使用递归,查看Tree的实现代码,是把比根节点小的放在左节点,比它小的放在右节点
于是只要实现一个二叉树的中序遍历即可顺序输出

 

https://tour.golang.org/concurrency/10

Exercise: Web Crawler

  1 package main
  2 
  3 import (
  4     "fmt"
  5     "sync"
  6 )
  7 
  8 type Fetcher interface {
  9     // Fetch returns the body of URL and
 10     // a slice of URLs found on that page.
 11     Fetch(url string) (body string, urls []string, err error)
 12 }
 13 
 14 // Crawl uses fetcher to recursively crawl
 15 // pages starting with url, to a maximum of depth.
 16 func Crawl(url string, depth int, fetcher Fetcher, c *urlSync, wg *sync.WaitGroup) {
 17     // TODO: Fetch URLs in parallel.
 18     // TODO: Don't fetch the same URL twice.
 19     // This implementation doesn't do either:
 20     defer wg.Done()
 21     if depth <= 0 {
 22         return
 23     }
 24 
 25     c.mux.Lock()
 26     if _, ok := c.v[url]; ok {
 27         c.mux.Unlock()
 28         return
 29     }
 30     c.v[url] = 1
 31     body, urls, err := fetcher.Fetch(url)
 32     c.mux.Unlock()
 33 
 34     if err != nil {
 35         fmt.Println(err)
 36         return
 37     }
 38     fmt.Printf("found: %s %q\n", url, body)
 39 
 40     for _, u := range urls {
 41         wg.Add(1)
 42         go Crawl(u, depth-1, fetcher, c, wg)
 43     }
 44     return
 45 }
 46 
 47 func main() {
 48     urlCache := urlSync{v: make(map[string]int)}
 49     var wg sync.WaitGroup
 50     wg.Add(1)
 51     go Crawl("http://golang.org/", 4, fetcher, &urlCache, &wg)
 52     wg.Wait()
 53 }
 54 
 55 // fakeFetcher is Fetcher that returns canned results.
 56 type fakeFetcher map[string]*fakeResult
 57 
 58 //url cache
 59 type urlSync struct {
 60     v   map[string]int
 61     mux sync.Mutex
 62 }
 63 
 64 type fakeResult struct {
 65     body string
 66     urls []string
 67 }
 68 
 69 func (f fakeFetcher) Fetch(url string) (string, []string, error) {
 70     if res, ok := f[url]; ok {
 71         return res.body, res.urls, nil
 72     }
 73     return "", nil, fmt.Errorf("not found: %s", url)
 74 }
 75 
 76 // fetcher is a populated fakeFetcher.
 77 var fetcher = fakeFetcher{
 78     "http://golang.org/": &fakeResult{
 79         "The Go Programming Language",
 80         []string{
 81             "http://golang.org/pkg/",
 82             "http://golang.org/cmd/",
 83         },
 84     },
 85     "http://golang.org/pkg/": &fakeResult{
 86         "Packages",
 87         []string{
 88             "http://golang.org/",
 89             "http://golang.org/cmd/",
 90             "http://golang.org/pkg/fmt/",
 91             "http://golang.org/pkg/os/",
 92         },
 93     },
 94     "http://golang.org/pkg/fmt/": &fakeResult{
 95         "Package fmt",
 96         []string{
 97             "http://golang.org/",
 98             "http://golang.org/pkg/",
 99         },
100     },
101     "http://golang.org/pkg/os/": &fakeResult{
102         "Package os",
103         []string{
104             "http://golang.org/",
105             "http://golang.org/pkg/",
106         },
107     },
108 }
View Code

 

转载于:https://www.cnblogs.com/kira-trash-can/p/7932478.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值