练习:循环与函数

(1)题目

为了练习函数与循环,我们来实现一个平方根函数:用牛顿法实现平方根函数。

计算机通常使用循环来计算 x 的平方根。从某个猜测的值 z 开始,我们可以根据 z² 与 x 的近似度来调整 z,产生一个更好的猜测:

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

重复调整的过程,猜测的结果会越来越精确,得到的答案也会尽可能接近实际的平方根。

在提供的 func Sqrt 中实现它。无论输入是什么,对 z 的一个恰当的猜测为 1。 要开始,请重复计算 10 次并随之打印每次的 z 值。观察对于不同的值 x(1、2、3 ...), 你得到的答案是如何逼近结果的,猜测提升的速度有多快。

提示:用类型转换或浮点数语法来声明并初始化一个浮点数值:

z := 1.0
z := float64(1)

然后,修改循环条件,使得当值停止改变(或改变非常小)的时候退出循环。观察迭代次数大于还是小于 10。 尝试改变 z 的初始猜测,如 x 或 x/2。你的函数结果与标准库中的 math.Sqrt 接近吗?

(2)代码

循环10次:

package main

import (
"fmt"
"math"
) func Sqrt(x float64) float64 {
z := 1.0
for i:= 0;i < 10;i++{
z -= (z*z-x)/(2*z)
fmt.Printf("i = %d, z = %f\n", i, z)
}
return z
} func main() {
fmt.Println(Sqrt(2))
fmt.Println(math.Sqrt(2))
}

无限逼近:

package main

import (
"fmt"
"math"
) func Sqrt(x float64) float64 {
z := 1.0
i := 0
for math.Abs( z*z-x) > 1e-10 {
z -= (z*z-x)/(2*z)
fmt.Printf("i = %d, z = %f\n", i, z)
i += 1
}
return z
} func main() {
fmt.Println(Sqrt(2))
fmt.Println(math.Sqrt(2))
}

练习:切片

(1)切片

实现 Pic。它应当返回一个长度为 dy 的切片,其中每个元素是一个长度为 dx,元素类型为 uint8 的切片。当你运行此程序时,它会将每个整数解释为灰度值(好吧,其实是蓝度值)并显示它所对应的图像。

图像的选择由你来定。几个有趣的函数包括 (x+y)/2x*yx^yx*log(y) 和 x%(y+1)

(提示:需要使用循环来分配 [][]uint8 中的每个 []uint8;请使用 uint8(intValue) 在类型之间转换;你可能会用到 math 包中的函数。)

(2)代码

package main

import "golang.org/x/tour/pic"

func Pic(dx, dy int) [][]uint8 {
result := make([][]uint8,dy)
for i := 0; i < dy; i++{
result[i] = make([]uint8,dx)
for j := 0; j < dx; j++{
              //更改此句,可得到不同的结果
result[i][j] = uint8(i*j)
}
}
return result
} func main() {
pic.Show(Pic)
}

(3)结果

aaarticlea/png;base64,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" alt="" width="256" height="256" />

练习:映射

(1)题目

实现 WordCount。它应当返回一个映射,其中包含字符串 s 中每个“单词”的个数。函数 wc.Test 会对此函数执行一系列测试用例,并输出成功还是失败。

你会发现 strings.Fields 很有帮助。

(2)代码

package main

import (
"golang.org/x/tour/wc"
"strings"
) func WordCount(s string) map[string]int {
result := strings.Fields(s)
m := make(map[string]int)
for _, word := range result{
m[word]++
}
return m
} func main() {
wc.Test(WordCount)
}

(3)结果

PASS
f("I am learning Go!") =
map[string]int{"Go!":1, "I":1, "am":1, "learning":1}
PASS
f("The quick brown fox jumped over the lazy dog.") =
map[string]int{"The":1, "brown":1, "dog.":1, "fox":1, "jumped":1, "lazy":1, "over":1, "quick":1, "the":1}
PASS
f("I ate a donut. Then I ate another donut.") =
map[string]int{"I":2, "Then":1, "a":1, "another":1, "ate":2, "donut.":2}
PASS
f("A man a plan a canal panama.") =
map[string]int{"A":1, "a":2, "canal":1, "man":1, "panama.":1, "plan":1}

练习:斐波那契闭包

(1)题目

让我们用函数做些好玩的事情。

实现一个 fibonacci 函数,它返回一个函数(闭包),该闭包返回一个斐波纳契数列 `(0, 1, 1, 2, 3, 5, ...)`。

(2)代码

package main

import "fmt"

// 返回一个“返回int的函数”
func fibonacci() func() int {
sum := 0
res1 := 0
res2 := 1
i := 0
return func() int{
if i == 0{
sum = res1
}else if i == 1{
sum = res2
}else{
sum = res1 + res2
res1 = res2
res2 = sum
}
i += 1
return sum
}
} func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}

练习:Stringer

(1)题目

通过让 IPAddr 类型实现 fmt.Stringer 来打印点号分隔的地址。

例如,IPAddr{1, 2, 3, 4} 应当打印为 "1.2.3.4"

(2)代码

package main

import "fmt"

type IPAddr [4]byte

// TODO: 给 IPAddr 添加一个 "String() string" 方法
func (addr IPAddr) String() string{
return fmt.Sprintf("%v.%v.%v.%v\n",addr[0],addr[1],addr[2],addr[3])
} func main() {
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)
}
}

练习:错误

(1)题目

从之前的练习中复制 Sqrt 函数,修改它使其返回 error 值。

Sqrt 接受到一个负数时,应当返回一个非 nil 的错误值。复数同样也不被支持。

创建一个新的类型

type ErrNegativeSqrt float64

并为其实现

func (e ErrNegativeSqrt) Error() string

方法使其拥有 error 值,通过 ErrNegativeSqrt(-2).Error() 调用该方法应返回 "cannot Sqrt negative number: -2"

注意: 在 Error 方法内调用 fmt.Sprint(e) 会让程序陷入死循环。可以通过先转换 e 来避免这个问题:fmt.Sprint(float64(e))。这是为什么呢?

修改 Sqrt 函数,使其接受一个负数时,返回 ErrNegativeSqrt 值。

(2)代码

package main

import (
"fmt"
"math"
) func Sqrt(x float64) (float64, error) {
if(x < 0){
return x, ErrNegativeSqrt(x)
}
return math.Sqrt(x), nil
} func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
} type ErrNegativeSqrt float64 func (num ErrNegativeSqrt) Error() string{
return fmt.Sprintf("cannot Sqrt negative number : %f\n", num)
}

练习:Reader

(1)题目

实现一个 Reader 类型,它产生一个 ASCII 字符 'A' 的无限流。

(2)代码

package main

import "golang.org/x/tour/reader"

type MyReader struct{}

// TODO: 给 MyReader 添加一个 Read([]byte) (int, error) 方法

func (read MyReader) Read(b []byte) (int, error) {
b[0] = 'A'
return 1, nil
} func main() {
reader.Validate(MyReader{})
}

(3)结果

OK!

Program exited.

练习:rot13Reader

(1)题目

有种常见的模式是一个 io.Reader 包装另一个 io.Reader,然后通过某种方式修改其数据流。

例如,gzip.NewReader 函数接受一个 io.Reader(已压缩的数据流)并返回一个同样实现了 io.Reader 的 *gzip.Reader(解压后的数据流)。

编写一个实现了 io.Reader 并从另一个 io.Reader 中读取数据的 rot13Reader,通过应用 rot13 代换密码对数据流进行修改。

rot13Reader 类型已经提供。实现 Read 方法以满足 io.Reader

(2)代码

package main

import (
"io"
"os"
"strings"
) type rot13Reader struct {
r io.Reader
} func rot13(b byte) byte{
if (b >= 'A' && b <= 'M') || (b >= 'a' && b <= 'm'){
b += 13
}else if (b >= 'N' && b <= 'Z') || (b >= 'n' && b <= 'z'){
b -= 13
}
return b
} func (reader rot13Reader) Read(b []byte)(int, error){
n, e := reader.r.Read(b)
for i := 0; i < n;i++{
b[i] = rot13(b[i])
}
return n,e
} func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}

(3)结果

You cracked the code!
Program exited.

练习:图像

(1)题目

还记得之前编写的图片生成器 吗?我们再来编写另外一个,不过这次它将会返回一个 image.Image 的实现而非一个数据切片。

定义你自己的 Image 类型,实现必要的方法并调用 pic.ShowImage

Bounds 应当返回一个 image.Rectangle ,例如 image.Rect(0, 0, w, h)

ColorModel 应当返回 color.RGBAModel

At 应当返回一个颜色。上一个图片生成器的值 v 对应于此次的 color.RGBA{v, v, 255, 255}

(2)代码

package main

import (
"golang.org/x/tour/pic"
"image"
"image/color"
) type Image struct{
width int
length int
} func (i Image) ColorModel() color.Model{
return color.RGBAModel
} func (i Image) Bounds() image.Rectangle{
return image.Rect(0,0,i.width,i.length)
} func (i Image) At(x, y int) color.Color{
return color.RGBA{uint8(x), uint8(y), 255, 255}
} func main() {
m := Image{150,150}
pic.ShowImage(m)
}

(3)结果

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAIAAACzY+a1AAABdUlEQVR4nOzRAQnAABDDwA7ev+WNyQjcUWogt73PZt3df5RJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZJmCdhnoR5EuZ9AQAA//9dBASCgym5DgAAAABJRU5ErkJggg==" alt="" width="150" height="150" />

练习:等价二叉查找树

(1)题目

1. 实现 Walk 函数。

2. 测试 Walk 函数。

函数 tree.New(k) 用于构造一个随机结构的已排序二叉查找树,它保存了值 k2k3k, ..., 10k

创建一个新的信道 ch 并且对其进行步进:

go Walk(tree.New(1), ch)

然后从信道中读取并打印 10 个值。应当是数字 1, 2, 3, ..., 10

3. 用 Walk 实现 Same 函数来检测 t1 和 t2 是否存储了相同的值。

4. 测试 Same 函数。

Same(tree.New(1), tree.New(1)) 应当返回 true,而 Same(tree.New(1), tree.New(2)) 应当返回 false

Tree 的文档可在这里找到。

(2)代码

package main

import(
"golang.org/x/tour/tree"
"fmt"
) // Walk 步进 tree t 将所有的值从 tree 发送到 channel ch。
func Walk(t *tree.Tree, ch chan int){
if t == nil{
return
}
Walk(t.Left, ch)
ch <- t.Value
Walk(t.Right, ch)
} func Same(t1, t2 *tree.Tree) bool{
ch1 := make(chan int)
ch2 := make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
for i := 0; i < 10; i++{
x, y := <-ch1, <-ch2
if x != y{
return false
}
}
return true
} func main(){
fmt.Println(Same(tree.New(1), tree.New(3)))
}

练习:Web爬虫

(1)题目

在这个练习中,我们将会使用 Go 的并发特性来并行化一个 Web 爬虫。

修改 Crawl 函数来并行地抓取 URL,并且保证不重复。

提示:你可以用一个 map 来缓存已经获取的 URL,但是要注意 map 本身并不是并发安全的!

(2)代码

package main

import (
"fmt"
"sync"
) type Cache struct{
cache map[string]bool
mutex sync.Mutex
} var cache Cache = Cache{cache:make(map[string]bool),} func (cache Cache) add(url string){
cache.mutex.Lock()
defer cache.mutex.Unlock()
cache.cache[url] = true
} func (cache Cache) isExist(url string) bool{
cache.mutex.Lock()
defer cache.mutex.Unlock()
_, ok := cache.cache[url]
if !ok {
cache.cache[url] = true
}
return ok
} type Fetcher interface {
// Fetch 返回 URL 的 body 内容,并且将在这个页面上找到的 URL 放到一个 slice 中。
Fetch(url string) (body string, urls []string, err error)
} // Crawl 使用 fetcher 从某个 URL 开始递归的爬取页面,直到达到最大深度。
func Crawl(url string, depth int, fetcher Fetcher, end chan bool) {
if depth <= 0 {
end <- true
return
} if cache.isExist(url){
//fmt.Println("Already Exist")
end <- true
return
}
cache.add(url) body, urls, err := fetcher.Fetch(url)
if err != nil {
fmt.Println(err)
end <- true
return
} fmt.Printf("found: %s %q\n", url, body)
subEnd := make(chan bool)
for _, u := range urls {
go Crawl(u, depth-1, fetcher, subEnd)
} for i := 0; i < len(urls); i++{
<- subEnd
}
end <- true
} func main() {
end := make(chan bool)
go Crawl("https://golang.org/", 4, fetcher, end)
for{
if <- end{
return
}
}
return
} // fakeFetcher 是返回若干结果的 Fetcher。
type fakeFetcher map[string]*fakeResult type fakeResult struct {
body string
urls []string
} func (f fakeFetcher) Fetch(url string) (string, []string, error) {
if res, ok := f[url]; ok {
return res.body, res.urls, nil
}
return "", nil, fmt.Errorf("not found: %s", url)
} // fetcher 是填充后的 fakeFetcher。
var fetcher = fakeFetcher{
"https://golang.org/": &fakeResult{
"The Go Programming Language",
[]string{
"https://golang.org/pkg/",
"https://golang.org/cmd/",
},
},
"https://golang.org/pkg/": &fakeResult{
"Packages",
[]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",
[]string{
"https://golang.org/",
"https://golang.org/pkg/",
},
},
"https://golang.org/pkg/os/": &fakeResult{
"Package os",
[]string{
"https://golang.org/",
"https://golang.org/pkg/",
},
},
}

(3)结果

found: https://golang.org/ "The Go Programming Language"
not found: https://golang.org/cmd/
found: https://golang.org/pkg/ "Packages"
found: https://golang.org/pkg/os/ "Package os"
found: https://golang.org/pkg/fmt/ "Package fmt"
04-28 13:31