携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
前言
之前在学习 Go 的官网教程时,发现它里面的练习好像没有答案,所以在这里分享一下自己写的解答,给新入门的 Gopher 提供一个对照,如果有疑问或者有更好的方法,欢迎大家在评论区里一起讨论。
英文版:A Tour of Go
中文版:Go 语言之旅
基础模块
循环与函数
英文版:golang.google.cn/tour/flowco…
中文版:tour.go-zh.org/flowcontrol…
题目简述
一句话概括就是:用牛顿法实现平方根函数。
求 的平方根,从某个猜测的值 开始,我们可以根据 与 的近似度来调整 ,产生一个更接近的猜测:
z -= (z*z - x) / (2*z)
重复调整的过程,猜测的结果会越来越精确,得到的答案也会尽可能接近实际的平方根的值。
上面的 是 到它所要到达的值(即 )的距离, 除以的 为 的导数,我们通过 的变化速度来改变 的调整量。这种通用方法叫做牛顿法,它对很多函数,特别是平方根而言非常有效。
解答
package main
import (
"fmt"
"math"
)
func Sqrt(x float64) float64 {
z := x / 2
d := 1.0
for math.Abs(d) > 1e-15 {
d = (z*z - x) / (2 * z)
z -= d
fmt.Println(z)
}
return z
}
func main() {
v:=2.0
fmt.Println("custom:",Sqrt(v))
fmt.Println("math:",math.Sqrt(v))
}
初值 可设为任意值(需保证为 float64 类型,或者进行类型转换),然后给改变量 d 设置一个很小的阈值,来使结果更加准确。迭代的次数与设置的初始值以及阈值有关。
切片
英文版:golang.google.cn/tour/morety…
中文版:tour.go-zh.org/moretypes/1…
题目简述
实现 Pic。它应当返回一个长度为 dy 的切片,其中每个元素是一个长度为 dx,元素类型为 uint8 的切片。当你运行此程序时,它会将每个整数解释为蓝度值并显示它所对应的图像。
设每一位置的值为
v,pic 包实际上调用了image.NewNRGBA(),然后令R=v, G=v, B=255, A=255,所以是蓝度值。
解答
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int) [][]uint8 {
img := make([][]uint8, dy)
for y := range img {
img[y] = make([]uint8, dx)
for x := range img[y] {
img[y][x] = uint8((x + y) / 2)
}
}
return img
}
func main() {
pic.Show(Pic)
}
初学者需要注意的一点是,二维切片中的每一项元素必须单独创建并初始化。
如果显示的是 base64 编码,可以通过这个网站转为图像: base64-to-image.com/
(x + y) / 2 的图像
x % (y + 1) 的图像
映射
英文版:golang.google.cn/tour/morety…
中文版:tour.go-zh.org/moretypes/2…
题目简述
实现 WordCount。它应当返回一个映射,其中包含字符串 s 中每个“单词”的个数。函数 wc.Test 会对此函数执行一系列测试用例,并输出成功还是失败。
解答
package main
import (
"golang.org/x/tour/wc"
"strings"
)
func WordCount(s string) map[string]int {
mp := make(map[string]int)
words := strings.Fields(s)
for _, v := range words {
mp[v]++
}
return mp
}
func main() {
wc.Test(WordCount)
}
strings.Fields() 会分割被空白字符围绕的字符串,然后返回一个字符串切片。遍历切片,统计字符串个数即可。这里可能会有人想用 ,ok 来检查字符串是否已经在映射中,然后分两种情况操作,这样也可以。但实际上, make 在创建映射时已经帮我们把空间初始化为零值,我们可以很方便地直接使用它。
斐波纳契闭包
英文版:golang.google.cn/tour/morety…
中文版:tour.go-zh.org/moretypes/2…
题目简述
实现一个 fibonacci 函数,它返回一个函数(闭包),该闭包返回一个斐波纳契数列 (0, 1, 1, 2, 3, 5, ...)。
解答
package main
import "fmt"
func fibonacci() func() int {
i := 0
a, b := 0, 1
return func() int {
if i == 0 {
i++
return 0
} else {
a, b = b, a+b
return a
}
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
由于数列是从 0 开始的,所以我们需要一个额外的标记,来给第一次操作做特判。或者你也可以使用以下的形式:
func fibonacci() func() int {
a, b, c := 0, 0, 1
return func() int {
a, b, c = b, c, b+c
return a
}
}
这种形式看起来更简洁一些。
总结
本篇文章是对基础模块的习题解答,包括循环、切片、映射和闭包的知识。如果大家有更好的答案,欢迎在评论区留言。
最后,如果本篇文章对你有所帮助,求 点赞、收藏、评论,感谢支持 ✧(≖ ◡ ≖✿