Go实战--go中函数递归(recursion)的使用(The way to go)
来源:互联网 发布:电脑课教学软件 编辑:程序博客网 时间:2024/04/20 10:51
生命不止,继续 go go go !!!
什么是递归
Technically, a recursive function is a function that makes a call to itself. To prevent infinite recursion, you need an if-else statement (of some sort) where one branch makes a recursive call, and the other branch does not. The branch without a recursive call is usually the base case (base cases do not make recursive calls to the function).
有耐心的读读上面这段英文,然后默认你已经了解了什么是递归,那就开始实战之旅吧。
斐波那契数列(Fibonacci)
大概所有的语言学习递归的时候,都会写Fibonacci数列吧。
简单粗暴,直接上代码了:
package mainimport "fmt"func fib(n int) uint { if n == 0 { return 0 } else if n == 1 { return 1 } else { return fib(n-1) + fib(n-2) }}func main() { n := 10 fmt.Println(fib(n))}
输出:55
通过闭包实现Fibonacci
go中允许使用函数闭包,我们之后会专门用一篇博客分享golang中的closure。
package mainimport "fmt"// fibonacci is a function that returns// a function that returns an int.func fibonacci() func() int { a := 0 b := 1 f := func() int { s := a a = b b = s + b return s } return f}func main() { f := fibonacci() for i := 0; i < 55; i++ { fmt.Println(f()) }}
通过递归打印html中的所有链接
下面的这个实战项目出自《The Go Programming Language》,可以翻阅。
其中源码的github地址:https://github.com/adonovan/gopl.io/
这里使用了golang.org/x/net/html包,自己去go get即可。从https://github.com/golang/net下载,然后把目录改成golang.org/x/net。
文档:
https://godoc.org/golang.org/x/net/html#example-Parse
下面就言归正传了:
递归visit函数:
func visit(links []string, n *html.Node) []string { if n.Type == html.ElementNode && n.Data == "a" { for _, a := range n.Attr { if a.Key == "href" { links = append(links, a.Val) } } } for c := n.FirstChild; c != nil; c = c.NextSibling { links = visit(links, c) } return links}
从html文件中读取所有链接:
package mainimport ( "fmt" "io/ioutil" "os" "strings" "golang.org/x/net/html")func main() { data, _ := ioutil.ReadFile("test.html") doc, err := html.Parse(strings.NewReader(string(data[:]))) if err != nil { fmt.Fprintf(os.Stderr, "findlinks1: %v\n", err) os.Exit(1) } for _, link := range visit(nil, doc) { fmt.Println(link) }}func visit(links []string, n *html.Node) []string { if n.Type == html.ElementNode && n.Data == "a" { for _, a := range n.Attr { if a.Key == "href" { links = append(links, a.Val) } } } for c := n.FirstChild; c != nil; c = c.NextSibling { links = visit(links, c) } return links}
通过管道读取某网址的所有链接:
想看一个Linux命令吧:
history | less
如果你懂这是什么意思,那我们就继续。
先通过fetch一个url:
package mainimport ( "fmt" "io/ioutil" "net/http" "os")func main() { for _, url := range os.Args[1:] { resp, err := http.Get(url) if err != nil { fmt.Fprintf(os.Stderr, "fetch: %v\n", err) os.Exit(1) } b, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err) os.Exit(1) } fmt.Printf("%s", b) }}
验证一下:
然后重写上面的文件,把从文件读取改为从标准输入读取:
package mainimport ( "fmt" "os" "golang.org/x/net/html")func main() { doc, err := html.Parse(os.Stdin) if err != nil { fmt.Fprintf(os.Stderr, "findlinks1: %v\n", err) os.Exit(1) } for _, link := range visit(nil, doc) { fmt.Println(link) }}func visit(links []string, n *html.Node) []string { if n.Type == html.ElementNode && n.Data == "a" { for _, a := range n.Attr { if a.Key == "href" { links = append(links, a.Val) } } } for c := n.FirstChild; c != nil; c = c.NextSibling { links = visit(links, c) } return links}
接下来就是通过管道执行了:
main.exe https://github.com/adonovan/gopl.io | D:\go_workspace\src\function_recursion\function_recursion.exe
可以看到输出结果:
- Go实战--go中函数递归(recursion)的使用(The way to go)
- Go实战--go中函数(function)和方法(method)的使用(The way to go)
- Go实战--go中使用libphonenumber(The way to go)
- Go实战--go中使用cookie(The way to go)
- Go实战--go中使用rpc(The way to go)
- Go实战--go中编码转换(The way to go)
- Go实战--net/http中JSON的使用(The way to go)
- Go实战--go中使用google/protobuf(The way to go)
- Go实战--go中使用base64加密(The way to go)
- Go实战--go中使用hmac sha256(The way to go)
- Go实战--go中一些有用的代码片段(The way to go)
- Go实战--go语言中执行shell脚本(The way to go)
- The way to go !
- Go实战--golang新手入门常见错误(The way to go)
- Go实战--golang生成uuid(The way to go)
- Go语言学习之函数(The way to go)
- Go实战--实现一个自己的网络请求日志httplogger(The way to go)
- Go实战--实现一个简单的tcp服务端和客户端(The way to go)
- 进程render要读取一个scene.dat文件过程(normal and mmap)
- Python简单处理图片
- 10道Struts2面试题
- Spring事务异常回滚,捕获异常不抛出就不会回滚
- 测试主管如何规范公司的测试流程?
- Go实战--go中函数递归(recursion)的使用(The way to go)
- SOJ 1303. Job Assignment 与 KM算法模版
- Android 开源框架Universal-Image-Loader完全解析(三)---源代码解读
- 激光雷达学习笔记(五)圆弧
- 命令行选项的处理
- 困在栅栏里的凯撒
- tcp断开侦测
- ArcGIS水文分析实战教程(2)ArcGIS水文分析工具的基本原理
- 创业成长系列.搭建基础