go-tour练习解答

简介:

go-tour对于想学习golang的人来说是一个很好的教程。

首先go-tour是有web版本,但是需要FQ。如果不能FQ的,也可以在google code上自己下载go-tour源码,go build,run一下,在自己的机器上就可以跑这个教程了。

提醒下,如果是后者,这篇文章中的程序对应的import包就需要进行相应修改了。

下面给出我的go-tour中的Exercise的解答(在web上已经测试通过)

Exercise: Loops and Functions

第一个循环10次:

复制代码
package main
import (
     "fmt"
)

func Sqrt(x float64) float64 {
     z := float64(1)
     for i := 0; i <= 10; i++ {
          z = z - (z*z - x) / (2 * z)
     }
     return z
}

func main() {
     fmt.Println(Sqrt(2))
}
复制代码

第二次无限接近:

复制代码
package main

import (
     "fmt"
     "math"
)

func Sqrt(x float64) float64 {
     z := float64(1)

     for {
          y := z - (z*z - x) / (2 * z)
          if math.Abs(y - z) < 1e-10 {
               return y
          }
          z = y;
     }
     return z
}



func main() {
     fmt.Println(Sqrt(2))
     fmt.Println(math.Sqrt(2))
}
复制代码

Exercise: Maps

复制代码
package main

import (
     "tour/wc"
     "strings"
)

func WordCount(s string) map[string]int {
     ret := make(map[string]int)

     arr := strings.Fields(s)
     for _, val := range arr {
          ret[val]++
     }
     return ret
}

func main() {
     wc.Test(WordCount)
}
复制代码

Exercise: Slices

复制代码
package main

import "tour/pic"

func Pic(dx, dy int) [][]uint8 {
     ret := make([][]uint8, dy)
     for i:=0; i<dy; i++ {
          ret[i] = make([]uint8, dx)
          for j:=0; j<dx; j++ {
               ret[i][j] = uint8(i*j)
          }
     }
     return ret
}

func main() {
     pic.Show(Pic)
}
复制代码

Exercise: Fibonacci closure

复制代码
package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
     sum1 := 0
     sum2 := 1
     return func() int{
          out := sum1 + sum2
          sum1 = sum2
          sum2 = out
          return out
         
     }
}

func main() {
     f := fibonacci()
     for i := 0; i < 10; i++ {
          fmt.Println(f())
     }
}
复制代码

Advanced Exercise: Complex cube roots

复制代码
package main

import (
     "fmt"
     "math/cmplx"
     )

func Cbrt(x complex128) complex128 {
     z := complex128(1)
     for {
          if y := z-(cmplx.Pow(z,3) - x)/(3 * z * z); cmplx.Abs(y - z) < 1e-10 {
               return y
          } else {
               z = y
          }
     }
     return z
}

func main() {
     fmt.Println(Cbrt(2))
}
复制代码

Exercise: Errors

复制代码
package main

import (
     "fmt"
     "math"
)

type ErrNegativeSqrt float64

func (e ErrNegativeSqrt) Error() string {
     return "cannot Sqrt negative number:" + fmt.Sprint(float64(e))
}

func Sqrt(f float64) (float64, error) {
     if f < 0 {
          return 0, ErrNegativeSqrt(f)
     }
    
     z := float64(1)
     for {
          y := z - (z*z-f)/(2*z)
          if math.Abs(y-z) < 1e-10 {
               return y, nil
          }
          z = y
     }
     return z, nil
}

func main() {
     fmt.Println(Sqrt(2))
     fmt.Println(Sqrt(-2))
}
复制代码

Exercise: Images

复制代码
package main

import (
     "image"
     "tour/pic"
     "image/color"
)

type Image struct{
     W int
     H int
}

func(self Image) Bounds() image.Rectangle {
     return image.Rect(0, 0, self.W, self.H)
}

func(self Image) ColorModel() color.Model {
     return color.RGBAModel
}

func(self Image) At(x,y int) color.Color {
     return color.RGBA{uint8(x), uint8(y), 255, 255}
}

func main() {
     m := Image{W:100, H:100}
     pic.ShowImage(m)
}
复制代码

Exercise: Rot13 Reader

复制代码
package main

import (
     "io"
     "os"
     "strings"
)

type rot13Reader struct {
     r io.Reader
}

func(self rot13Reader)Read(p []byte) (n int, err error){
     self.r.Read(p)
     leng := len(p)
     for i := 0; i < leng; i++ {
          switch{
          case p[i] >= 'a' && p[i] < 'n':
               fallthrough
          case p[i] >= 'A' && p[i] < 'N':
               p[i] = p[i] + 13
          case p[i] >= 'n' && p[i] <= 'z':
               fallthrough
          case p[i] >= 'N' && p[i] <= 'Z':
               p[i] = p[i] - 13
          }
     }
     return leng, nil
}


func main() {
     s := strings.NewReader(
          "Lbh penpxrq gur pbqr!")
     r := rot13Reader{s}
     io.Copy(os.Stdout, &r)
}
复制代码

Exercise: Equivalent Binary Trees

复制代码
package main

import (
     "tour/tree"
     )

// Walk walks the tree t sending all values
// from the tree to the 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)
}

// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
     ch1 := make(chan int)
     ch2 := make(chan int)
     go func() {
          Walk(t1, ch1)
          ch1 <- 0
     }()
    
     go func() {
          Walk(t2, ch2)
          ch2 <- 0
     }()
    
     for {
          t1 := <-ch1
          t2 := <-ch2
          if t1 == 0 && t2 == 0 {
               return true;
          }
         
          if t1 == t2 {
               continue;
          } else {
               return false;
          }
     }
     return true
}

func main() {
     ch := make(chan int)
     go func() {
          Walk(tree.New(1), ch)
          ch <- 0
     }()
    
     for {
          t := <-ch
          if t == 0 {
               break;
          }
          println(t)
     }
    
     println(Same(tree.New(1), tree.New(2)))
}
复制代码

Exercise: Web Crawler

复制代码
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)
}

// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher, out chan string, end chan bool) {
     if depth <= 0 {
          end <- true
          return
     }

     if _, ok := crawled[url]; ok {
          end <- true
          return
     }
     crawledMutex.Lock()
     crawled[url] = true
     crawledMutex.Unlock()

     body, urls, err := fetcher.Fetch(url)
     if err != nil {
          out <- fmt.Sprintln(err)
          end <- true
          return
     }

     out <- fmt.Sprintf("found: %s %q\n", url, body)
     subEnd := make(chan bool)
     for _, u := range urls {
          go Crawl(u, depth-1, fetcher, out, subEnd)
     }

     for i := 0; i < len(urls); i++ {
          <- subEnd
     }

     end <- true
}

var crawled = make(map[string]bool)
var crawledMutex sync.Mutex

func main() {
     out := make(chan string)
     end := make(chan bool)

     go Crawl("http://golang.org/", 4, fetcher, out, end)
     for {
          select {
          case t := <- out:
               fmt.Print(t)
          case <- end:
               return
          }
     }
}


// 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) (string, []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{
     "http://golang.org/": &fakeResult{
          "The Go Programming Language",
          []string{
               "http://golang.org/pkg/",
               "http://golang.org/cmd/",
          },
     },
     "http://golang.org/pkg/": &fakeResult{
          "Packages",
          []string{
               "http://golang.org/",
               "http://golang.org/cmd/",
               "http://golang.org/pkg/fmt/",
               "http://golang.org/pkg/os/",
          },
     },
     "http://golang.org/pkg/fmt/": &fakeResult{
          "Package fmt",
          []string{
               "http://golang.org/",
               "http://golang.org/pkg/",
          },
     },
     "http://golang.org/pkg/os/": &fakeResult{
          "Package os",
          []string{
               "http://golang.org/",
               "http://golang.org/pkg/",
          },
     },
}
复制代码
目录
相关文章
|
JavaScript Go 前端开发
|
1天前
|
设计模式 Go 调度
Golang深入浅出之-Go语言中的并发模式:Pipeline、Worker Pool等
【5月更文挑战第1天】Go语言并发模拟能力强大,Pipeline和Worker Pool是常用设计模式。Pipeline通过多阶段处理实现高效并行,常见问题包括数据竞争和死锁,可借助通道和`select`避免。Worker Pool控制并发数,防止资源消耗,需注意任务分配不均和goroutine泄露,使用缓冲通道和`sync.WaitGroup`解决。理解和实践这些模式是提升Go并发性能的关键。
11 2
|
1天前
|
JSON 监控 安全
Golang深入浅出之-Go语言中的反射(reflect):原理与实战应用
【5月更文挑战第1天】Go语言的反射允许运行时检查和修改结构,主要通过`reflect`包的`Type`和`Value`实现。然而,滥用反射可能导致代码复杂和性能下降。要安全使用,应注意避免过度使用,始终进行类型检查,并尊重封装。反射的应用包括动态接口实现、JSON序列化和元编程。理解反射原理并谨慎使用是关键,应尽量保持代码静态类型。
9 2
|
1天前
|
Go
Golang深入浅出之-Go语言代码质量与规范:遵循Gofmt与Linting
【5月更文挑战第1天】本文讨论了如何使用`gofmt`和Lint工具提升Go代码质量。`gofmt`负责自动格式化代码,保持风格统一,而Lint工具如`golint`、`govet`、`staticcheck`则进行静态分析,检查潜在错误和未使用的变量。通过集成`gofmt`检查到CI/CD流程,避免格式冲突,并使用Lint工具发现并修复问题,如未处理的错误、不规范命名。遵循这些最佳实践,可提高代码可读性、团队协作效率和可维护性。
9 3
|
2天前
|
JSON 安全 Java
2024年的选择:为什么Go可能是理想的后端语言
【4月更文挑战第27天】Go语言在2024年成为后端开发的热门选择,其简洁设计、内置并发原语和强大工具链备受青睐。文章探讨了Go的设计哲学,如静态类型、垃圾回收和CSP并发模型,并介绍了使用Gin和Echo框架构建Web服务。Go的并发通过goroutines和channels实现,静态类型确保代码稳定性和安全性,快速编译速度利于迭代。Go广泛应用在云计算、微服务等领域,拥有丰富的生态系统和活跃社区,适合作为应对未来技术趋势的语言。
8 0
|
2天前
|
Go 开发者
Golang深入浅出之-Go语言项目构建工具:Makefile与go build
【4月更文挑战第27天】本文探讨了Go语言项目的构建方法,包括`go build`基本命令行工具和更灵活的`Makefile`自动化脚本。`go build`适合简单项目,能直接编译Go源码,但依赖管理可能混乱。通过设置`GOOS`和`GOARCH`可进行跨平台编译。`Makefile`适用于复杂构建流程,能定义多步骤任务,但编写较复杂。在选择构建方式时,应根据项目需求权衡,从`go build`起步,逐渐过渡到Makefile以实现更高效自动化。
9 2
|
2天前
|
存储 Go
Golang深入浅出之-Go语言依赖管理:GOPATH与Go Modules
【4月更文挑战第27天】Go语言依赖管理从`GOPATH`进化到Go Modules。`GOPATH`时代,项目结构混乱,可通过设置多个工作空间管理。Go Modules自Go 1.11起提供更现代的管理方式,通过`go.mod`文件控制依赖。常见问题包括忘记更新`go.mod`、处理本地依赖和模块私有化,可使用`go mod tidy`、`replace`语句和`go mod vendor`解决。理解并掌握Go Modules对现代Go开发至关重要。
7 2
|
2天前
|
安全 测试技术 Go
Golang深入浅出之-Go语言单元测试与基准测试:testing包详解
【4月更文挑战第27天】Go语言的`testing`包是单元测试和基准测试的核心,简化了测试流程并鼓励编写高质量测试代码。本文介绍了测试文件命名规范、常用断言方法,以及如何进行基准测试。同时,讨论了测试中常见的问题,如状态干扰、并发同步、依赖外部服务和测试覆盖率低,并提出了相应的避免策略,包括使用`t.Cleanup`、`t.Parallel()`、模拟对象和检查覆盖率。良好的测试实践能提升代码质量和项目稳定性。
7 1
|
2天前
|
运维 监控 Go
Golang深入浅出之-Go语言中的日志记录:log与logrus库
【4月更文挑战第27天】本文比较了Go语言中标准库`log`与第三方库`logrus`的日志功能。`log`简单但不支持日志级别配置和多样化格式,而`logrus`提供更丰富的功能,如日志级别控制、自定义格式和钩子。文章指出了使用`logrus`时可能遇到的问题,如全局logger滥用、日志级别设置不当和过度依赖字段,并给出了避免错误的建议,强调理解日志级别、合理利用结构化日志、模块化日志管理和定期审查日志配置的重要性。通过这些实践,开发者能提高应用监控和故障排查能力。
8 1
|
2天前
|
安全 Go
Golang深入浅出之-Go语言标准库中的文件读写:io/ioutil包
【4月更文挑战第27天】Go语言的`io/ioutil`包提供简单文件读写,适合小文件操作。本文聚焦`ReadFile`和`WriteFile`函数,讨论错误处理、文件权限、大文件处理和编码问题。避免错误的关键在于检查错误、设置合适权限、采用流式读写及处理编码。遵循这些最佳实践能提升代码稳定性。
6 0