MENU

假装学会 Go 语言

2020 年 02 月 08 日 • 阅读: 9137 • 后端

花两天时间刷了 Go 语言指南,语法比 C、C++ 和 Java 等简洁,但 切片协程 等涉及底层的内容可能会有坑,先贴一下练习题答案,有机会写个项目练练手。本文写于 2020.2.8,随着时间推移,题目可能发生变更,以下内容仅供参考。

循环与函数展开目录

牛顿迭代法 求平方根,公式在题目描述里已经给出,直接 循环 即可。

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 6:31, 8/2/2020,
  • * answer for https://tour.go-zh.org/flowcontrol/8
  • */
  • package main
  • import (
  • "fmt"
  • "math"
  • )
  • func Sqrt(x float64) float64 {
  • y := 1e-6
  • z := x / 2
  • for i := 1; ; i++ {
  • j := z
  • z -= (z*z - x) / (2 * z)
  • if math.Abs(j-z) <= y {
  • fmt.Printf("Loop counts: %v\n", i)
  • break
  • }
  • }
  • return z
  • }
  • func main() {
  • fmt.Println("Result of customized Sqrt(2): ", Sqrt(2))
  • fmt.Println("Result of builtin Sqrt(2) : ", math.Sqrt(2))
  • }

切片展开目录

操作 二维切片 为图片像素点赋值,类似其他语言的 二维数组

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 6:55, 8/2/2020,
  • * answer for https://tour.go-zh.org/moretypes/18
  • */
  • package main
  • import "golang.org/x/tour/pic"
  • func Pic(dx, dy int) [][]uint8 {
  • p := make([][]uint8, dy)
  • for i := range p {
  • p[i] = make([]uint8, dx)
  • for j := range p[i] {
  • p[i][j] = uint8(i * j)
  • }
  • }
  • return p
  • }
  • func main() {
  • pic.Show(Pic)
  • }

映射展开目录

统计一句话中每个单词出现的次数,提示使用 strings.Fields() 将句子分割成单词数组,Java 有类似工具类。

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 7:6, 8/2/2020,
  • * answer for https://tour.go-zh.org/moretypes/23
  • */
  • package main
  • import (
  • "golang.org/x/tour/wc"
  • "strings"
  • )
  • func WordCount(s string) map[string]int {
  • ret := make(map[string]int)
  • for _, w := range strings.Fields(s) {
  • //if ret[w] == 0 {
  • // ret[w] = 1
  • // continue
  • //}
  • ret[w] += 1
  • }
  • return ret
  • }
  • func main() {
  • wc.Test(WordCount)
  • }

斐波纳契闭包展开目录

闭包 下的 斐波纳契 数列实现,写过 JavaScript 应该很容易接受。

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 7:21, 8/2/2020,
  • * answer for https://tour.go-zh.org/moretypes/26
  • */
  • package main
  • import "fmt"
  • func fibonacci() func() int {
  • ret := 0
  • prev := -1
  • next := 1
  • return func() int {
  • ret = prev + next
  • prev = next
  • next = ret
  • return ret
  • }
  • }
  • func main() {
  • f := fibonacci()
  • for i := 0; i < 10; i++ {
  • fmt.Print(f()," ")
  • }
  • }

Stringer 展开目录

为类型实现 Stringer 接口,fmt.Print 系列方法会自动调用 String()Java 有类似特性。

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 7:27, 8/2/2020,
  • * answer for https://tour.go-zh.org/methods/18
  • */
  • package main
  • import (
  • "fmt"
  • )
  • type IPAddr [4]byte
  • func (addr IPAddr) String() string {
  • return fmt.Sprintf("%d.%d.%d.%d", 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)
  • }
  • }

错误展开目录

为类型实现 error 接口,fmt.Print 系列方法会自动调用 Error()

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 7:46, 8/2/2020,
  • * answer for https://tour.go-zh.org/methods/20
  • */
  • package main
  • import (
  • "fmt"
  • "math"
  • )
  • type ErrNegativeSqrt float64
  • func (e ErrNegativeSqrt) Error() string {
  • return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))
  • }
  • func sqrt(x float64) (float64, error) {
  • var err error = nil
  • if x < 0 {
  • err = ErrNegativeSqrt(x)
  • }
  • return math.Sqrt(x), err
  • }
  • func main() {
  • fmt.Println(sqrt(2))
  • fmt.Println(sqrt(-2))
  • }

Reader 展开目录

为类型实现 Reader 接口,即添加 read 方法。

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 7:53, 8/2/2020,
  • * answer for https://tour.go-zh.org/methods/22
  • */
  • package main
  • import "golang.org/x/tour/reader"
  • type MyReader struct {
  • }
  • func (reader MyReader) Read(b []byte) (int, error) {
  • for i := range b {
  • b[i] = 'A'
  • }
  • return len(b), nil
  • }
  • func main() {
  • reader.Validate(MyReader{})
  • }

rot13Reader 展开目录

练习 io 流的包装,示例是实现 rot13 代换码Java 有类似设计。

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 8:2, 8/2/2020,
  • * answer for https://tour.go-zh.org/methods/23
  • */
  • package main
  • import (
  • "io"
  • "os"
  • "strings"
  • )
  • type rot13Reader struct {
  • r io.Reader
  • }
  • func (rot13 rot13Reader) Read(b []byte) (int, error) {
  • c := make([]byte, len(b))
  • n, err := rot13.r.Read(c)
  • //if err == io.EOF {
  • // return 0, io.EOF
  • //}
  • for i := 0; i < n; i++ {
  • if c[i] >= 'A' && c[i] <= 'Z' {
  • b[i] = (c[i]-'A'+13)%26 + 'A'
  • } else if c[i] >= 'a' && c[i] <= 'z' {
  • b[i] = (c[i]-'a'+13)%26 + 'a'
  • } else {
  • b[i] = c[i]
  • }
  • }
  • return n, err
  • }
  • func main() {
  • s := strings.NewReader("Lbh penpxrq gur pbqr!")
  • r := rot13Reader{s}
  • io.Copy(os.Stdout, &r)
  • }

图像展开目录

实现 Image 接口

  • type Image interface {
  • // ColorModel returns the Image's color model.
  • ColorModel() color.Model
  • // Bounds returns the domain for which At can return non-zero color.
  • // The bounds do not necessarily contain the point (0, 0).
  • Bounds() Rectangle
  • // At returns the color of the pixel at (x, y).
  • // At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
  • // At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
  • At(x, y int) color.Color
  • }
  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 8:3, 8/2/2020,
  • * answer for https://tour.go-zh.org/methods/25
  • */
  • package main
  • import (
  • "golang.org/x/tour/pic"
  • "image"
  • "image/color"
  • )
  • type Image struct {
  • w, h int
  • }
  • func (img Image) ColorModel() color.Model {
  • return color.RGBAModel
  • }
  • func (img Image) Bounds() image.Rectangle {
  • return image.Rect(0, 0, img.w, img.h)
  • }
  • func (img Image) At(x, y int) color.Color {
  • v := uint8(x + y)
  • return color.RGBA{v, v, 255, 255}
  • }
  • func main() {
  • m := Image{100, 100}
  • pic.ShowImage(m)
  • }

等价二叉查找树展开目录

遍历二叉树,并用 协程 检测两棵树是否相等。

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 8:4, 8/2/2020,
  • * answer for https://tour.go-zh.org/concurrency/8
  • */
  • package main
  • import (
  • "fmt"
  • "golang.org/x/tour/tree"
  • )
  • 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++ {
  • if <-ch1 != <-ch2 {
  • return false
  • }
  • }
  • return true
  • }
  • func main() {
  • ch := make(chan int)
  • go Walk(tree.New(1), ch)
  • for i := 0; i < 10; i++ {
  • fmt.Print(<-ch, " ")
  • }
  • fmt.Println()
  • fmt.Println(Same(tree.New(1), tree.New(1)))
  • fmt.Println(Same(tree.New(1), tree.New(2)))
  • }

Web 爬虫展开目录

模拟 多线程 爬取网页内容,要求重复链接只爬一次,提示用 map 保存,关键是让主线程 等待 协程结束。

  • /*
  • * Copyright (c) 2020, LOGI. All rights reserved.
  • * This file is created by LOGI at 8:4, 8/2/2020,
  • * answer for https://tour.go-zh.org/concurrency/10
  • */
  • package main
  • import (
  • "fmt"
  • "sync"
  • )
  • type Fetcher interface {
  • Fetch(url string) (body string, urls []string, err error)
  • }
  • type FetchFlag struct {
  • fetched map[string]bool
  • sync.Mutex
  • }
  • var flag = &FetchFlag{fetched: make(map[string]bool)}
  • func Crawl(url string, depth int, fetcher Fetcher, ch chan int) {
  • if ch != nil {
  • defer func() { ch <- 1 }()
  • }
  • flag.Lock()
  • if depth <= 0 || flag.fetched[url] {
  • flag.Unlock()
  • return
  • }
  • body, urls, err := fetcher.Fetch(url)
  • flag.fetched[url] = true
  • flag.Unlock()
  • if err != nil {
  • fmt.Println(err)
  • return
  • }
  • fmt.Printf("found:%s %q\n", url, body)
  • newCh := make(chan int)
  • for _, u := range urls {
  • go Crawl(u, depth-1, fetcher, newCh)
  • }
  • for range urls {
  • <-newCh
  • }
  • }
  • func main() {
  • Crawl("https://golang.org/", 4, fetcher, nil)
  • }
  • type fakeResult struct {
  • body string
  • urls []string
  • }
  • type fakeFetcher map[string]*fakeResult
  • 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)
  • }
  • 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/",
  • },
  • },
  • }
TG 大佬群 QQ 大佬群

最后编辑于: 2020 年 10 月 20 日
返回文章列表 文章二维码
本页链接的二维码
打赏二维码
添加新评论

Loading captcha...

  • OωO
  • |´・ω・)ノ
  • ヾ(≧∇≦*)ゝ
  • (☆ω☆)
  • (╯‵□′)╯︵┴─┴
  •  ̄﹃ ̄
  • (/ω\)
  • ∠( ᐛ 」∠)_
  • (๑•̀ㅁ•́ฅ)
  • →_→
  • ୧(๑•̀⌄•́๑)૭
  • ٩(ˊᗜˋ*)و
  • (ノ°ο°)ノ
  • (´இ皿இ`)
  • ⌇●﹏●⌇
  • (ฅ´ω`ฅ)
  • (╯°A°)╯︵○○○
  • φ( ̄∇ ̄o)
  • ヾ(´・ ・`。)ノ"
  • ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
  • (ó﹏ò。)
  • Σ(っ °Д °;)っ
  • ( ,,´・ω・)ノ"(´っω・`。)
  • ╮(╯▽╰)╭
  • o(*////▽////*)q
  • >﹏<
  • ( ๑´•ω•) "(ㆆᴗㆆ)
  • (。•ˇ‸ˇ•。)
  • 泡泡
  • 阿鲁
  • 蛆音娘
  • 小埋
  • 颜文字

已有 2 条评论
  1. 强调几点:(该留言由系统自动生成!)
    1. 请不要刷广告,本站没有流量!
    2. 我不回复虚假邮箱,因为回复了你也看不到!
    3. 存在必须回复的隐藏内容时,可以直接使用表情框里的阿鲁表情!

  1. Darren.Li Darren.Li   Mac OS X 10.14.3  Google Chrome 79.0.3945.130

    两天刷完怎么做到了?果真没有不可能

    1. LOGI LOGI   Windows 10 x64 Edition  Google Chrome 80.0.3987.122

      @Darren.Li 因为没往深看,只是几页 hello world