[daily] Go language Bible - variable parameter exercises

Keywords: Go

1. Functions with variable number of parameters are called variable parameter functions, such as fmt.Printf and similar functions
2. Add the ellipsis "..." before the last parameter type in the parameter list
3. Although in the variable parameter function, the behavior of int type parameter looks like slice type, in fact, the variable parameter function is different from the function with slice as parameter
Different type: FMT. Printf (""% t \ n ", f)"
4. The suffix f of function name is a general naming standard, which means that the variable parameter function can receive Printf style formatted string
5. Interface {} indicates that the last parameter of the function can receive any type

Exercise 5.15: write variable parameter functions like sum, max and min. Consider how to handle max and min when parameters are not passed, and then write a version that receives at least one parameter.
Exercise 5.16: write a multi parameter version of strings.Join.

Exercise 5.17: write a multi parameter version of ElementsByTagName. The function receives an HTML node tree and any number of tag names, and returns all elements matching those tag names. Here are two examples:

func ElementsByTagName(doc *html.Node, name...string) []*html.Node
images := ElementsByTagName(doc, "img")
headings := ElementsByTagName(doc, "h1", "h2", "h3", "h4")

 

package main

import (
        "fmt"
        "golang.org/x/net/html"
        "net/http"
)

func main() {
        fmt.Println(max(1, 2, 3, 4, 2)) 
        fmt.Println(max())
        fmt.Println(join("-", "hello", "tsh", "hi"))

        resp, _ := http.Get("http://mail.sina.net")
        doc, _ := html.Parse(resp.Body)
        resp.Body.Close()
        tNodes := ElementsByTagName(doc, "p", "a")
        for _, v := range tNodes {
                ForEachNode(v)
                fmt.Println("------------------------")
        }   
}

/*
Exercise 5.15: write variable parameter functions like sum, max and min. Consider how to handle max and min when parameters are not passed, and then write a version that receives at least one parameter.
*/
func max(vals ...int) (int, error) {
        var m int 

        num := len(vals)
        if num == 0 { 
                return 0, fmt.Errorf("max: %s", "Pass at least one parameter")
        }   
        for _, v := range vals {
                if m < v { 
                        m = v 
                }   
        }   
        return m, nil 
}

/*
Exercise 5.16: write a multi parameter version of strings.Join.
*/
func join(sep string, strs ...string) (string, error) {
        var res string
        var num = len(strs)
        if num == 0 { 
                return "", fmt.Errorf("join: %s", "Pass at least one parameter")
        }   

        for i, v := range strs {
                if i == (num - 1) {
                        res += v
                } else {
                        res += v + sep
                }
        }
        return res, nil
}

/*
Exercise 5.17: write a multi parameter version of ElementsByTagName. The function receives an HTML node tree and any number of tag names, and returns all elements matching those tag names. Here are two examples:
*/
var nodes []*html.Node

func ElementsByTagName(n *html.Node, names ...string) []*html.Node {
        newNode := n
        for _, name := range names {
                if n.Type == html.ElementNode && n.Data == name {
                        nodes = append(nodes, newNode)
                }
        }
        for c := n.FirstChild; c != nil; c = c.NextSibling {
                //Variable parameter transmission characteristics
                ElementsByTagName(c, names...)
        }
        return nodes
}
func ForEachNode(n *html.Node) {
        fmt.Println(n.Data)
        for c := n.FirstChild; c != nil; c = c.NextSibling {
                ForEachNode(c)
        }
}

  

Posted by jalbey on Sun, 05 Apr 2020 12:22:04 -0700