Go language Bible - Chapter 5 functions - 5.3 multiple return values

Chapter 5 functions

Function allows us to package a statement sequence into a unit, and then call it many times from other parts of the program. The mechanism of function allows us to decompose a large work into small tasks. We have touched on functions before, and we will discuss more features of functions in this chapter

5.3 multiple return values

We all know that a function can have multiple return values. Next, let's continue to study the return values of functions

There are generally two function return values in many annotation libraries, one is the expected return value, and the other is the error message when the function fails

Let's take a look at the newly rewritten findlinks function. The newly modified findlinks can initiate HTTP requests by itself. Because both HTTP requests and parsing operations may fail, the findlinks function has two return values, each of which displays the link list and the other returns an error message

Generally speaking, the HTML parser can handle the error nodes of HTML pages and construct the HTML page structure, so parsing HTML rarely fails, which means that if findlinks fails, it is likely to be caused by I/O errors

func main() {
	for _, url := range os.Args[1:] {
		links,err := findlinks(url)
		if err != nil {
			fmt.Fprintf(os.Stderr,"findlinks2",err)
			continue
		}
		for _,link := range links {
			fmt.Println(link)
		}
	}
}
func findlinks(url string) ([]string,error) {
	resp,err := http.Get(url)
	if err != nil {
		return nil,err
	}
	if resp.StatusCode != http.StatusOK {
		resp.Body.Close()
		if err != nil {
			return nil, fmt.Errorf("getting %s: %s", url,resp.Status)
		}
	}
	doc, err:= html.Parse(resp.Body)
	resp.Body.Close()
	if err != nil {
		return nil,fmt.Errorf("parising %s as HTML :%v",url,err)
	}
	return visit(nil,doc),nil
}

In findlinks, there are four return statements. The first three times return error information, and the second and third times use fmt.Errof to output detailed error information. If findlinks ends successfully, the last set of parsed links is returned to the user

In findlinks, we must ensure that resp.Body is closed to release network resources. Although Go's garbage collection mechanism will recycle unused memory, it does not include operating system level resources, such as open files and network connections. Therefore, we must explicitly release these resources

The caller must explicitly assign multiple return values of a function to a variable

links, err := findLinks(url)

Within a function, another function call with multiple return values can be used as the return value. The return value types of the two functions are the same

func findLinkslog(url string)([]string, error) {
   log.Printf("findlinks %s", url)
   return findlinks(url)
}

Of course, a function parameter can also be the return value of another function

log.Println(findlinks(url))
links,err := findlinks(url)
log.Println(links,err)

The exact variable name can convey the meaning of the return value of the function

func Size(rect image.Rectangle)(width,height int)
func Split(path string)(dir,file string)
func HourMinsec(t time.Time)(hour,minute,second int)

Although accurate naming is very important, there is no need to ask for an appropriate name for each return value, especially for some habitual return values, such as bool for success or not

If all the return values of a function have explicit variable names, the return statement can omit the operands and call it bare return

func CountWordsAndImages(url string)(words,images int,err error){
   resp,err := http.Get(url)
   if err != nil {
      return
   }
   doc,err := html.Parse(resp.Body)
   resp.Body.Close()
   if err != nil {
      err = fmt.Errorf("parsing HTML :%s",err)
      return
   }
   words,images = countWordsAndImages(doc)
   return
}
func countWordsAndImages(n *html.Node) (words,images int){/*...*/}

Each return statement in the above code is equivalent to

return words, images, err

When a function returns multiple times, bare return can reduce the amount of code. This point should be conscious before the function is constructed, so as to decide whether to explicitly declare the return value. However, it should also be noted that Go initializes the return value to 0 at the beginning of the function body according to their type, so the first two returns are equivalent to the first two returns, equivalent to return 0,0,err, and the last return is equivalent to return words, image, nil. For this reason, we should not use bare return excessively

Tags: Go Back-end Functional Programming

Posted on Mon, 01 Nov 2021 13:54:24 -0400 by Satria Ox41464b