/* //!+output $ go build gopl.io/ch5/title1 $ ./title1 http://gopl.io The Go Programming Language $ ./title1 https://golang.org/doc/effective_go.html Effective Go - The Go Programming Language $ ./title1 https://golang.org/doc/gopher/frontpage.png title: https://golang.org/doc/gopher/frontpage.png has type image/png, not text/html //!-output */
import ( "fmt" "net/http" "os" "strings"
"golang.org/x/net/html" )
// Copied from gopl.io/ch5/outline2. funcforEachNode(n *html.Node, pre, post func(n *html.Node)) { if pre != nil { pre(n) } for c := n.FirstChild; c != nil; c = c.NextSibling { forEachNode(c, pre, post) } if post != nil { post(n) } }
// Check Content-Type is HTML (e.g., "text/html; charset=utf-8"). ct := resp.Header.Get("Content-Type") if ct != "text/html" && !strings.HasPrefix(ct, "text/html;") { resp.Body.Close() return fmt.Errorf("%s has type %s, not text/html", url, ct) }
doc, err := html.Parse(resp.Body) resp.Body.Close() if err != nil { return fmt.Errorf("parsing %s as HTML: %v", url, err) }
// Copied from gopl.io/ch5/outline2. funcforEachNode(n *html.Node, pre, post func(n *html.Node)) { if pre != nil { pre(n) } for c := n.FirstChild; c != nil; c = c.NextSibling { forEachNode(c, pre, post) } if post != nil { post(n) } }
for _, filename := range filenames { f, err := os.Open(filename) if err != nil { return err } defer f.Close() // NOTE: risky; could run out of file descriptors // ...process f... }
上面的程序可以修改为,包裹在一个函数中:
1 2 3 4 5 6 7 8 9 10 11 12 13
for _, filename := range filenames { if err := doFile(filename); err != nil { return err } } funcdoFile(filename string)error { f, err := os.Open(filename) if err != nil { return err } defer f.Close() // ...process f... }
错误与defer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
funcmain() { f(3) } funcf(x int) { fmt.Printf("f(%d)\n", x+0/x) // panics if x == 0 defer fmt.Printf("defer %d\n", x) f(x - 1) } When run, the program prints the following to the standard output: f(3) f(2) f(1) defer1 defer2 defer3
// 1, 1, 2, 3, 5, 8, 13, ... funcFibonacci()func()int { a, b := 0, 1 returnfunc()int { a, b = b, a+b return a } } functryDefer() { for i := 0; i < 100; i++ { defer fmt.Println(i) if i == 30 { // Uncomment panic to see // how it works with defer // panic("printed too many") } } }