golang learning notes 007 -- functions, packages and error handling

1. Function

func Function name (parameter list ) (Return value list){
	Execute statement...
	return Return value list
	}

2. Package

● Three functions of package
  ○ Distinguish functions with the same name,Variable identifier
  ○ When there are many program files,Can manage the project well
  ○ Control function,Variable and other access ranges,And scope
● matters needing attention
  ○ The package name of the file is usually the same as the folder name of the file,Generally lowercase letters
  ○ When a file wants to use other package functions or variables,You need to import the corresponding package first
  ○ Accessing other package functions,Variable time,The syntax is the package name.Function name
  ○ If the package name is long,go Language support aliasing packages.After alias,The original package name cannot be used
  ○ Under the same package,Cannot have the same function name or global variable
  ○ If you want to compile into an executable program file,You need to declare this package as main,Namely package main,If you write a library,Packages can be customized

3. Function calling mechanism

explain:
	● When calling a function,A new space is allocated to the function,The compiler will distinguish this new space from other stack spaces through its own processing
	● In the stack corresponding to each function,The data space is independent,No confusion
	● When a function calls the pen,The program will destroy the stack space corresponding to this function

4.return statement

The go function supports returning multiple values
● if multiple values are returned and you want to ignore a value when accepting, use_ The symbol indicates that the placeholder is ignored
● if a value is returned, (return value type list) may not be written ()

	package main
	import "fmt"
	
	func getSumAndSub (a int,b int) (int,int){
		sum := a + b
		sub := a - b
		return sum,sub
	}
	
	func main(){
		res1,res2 :=getSumAndSub(5,2)
		fmt.Printf("res1=%v res2=%v\n",res1,res2)//res1=7 res2=3
		res3,_ :=getSumAndSub(5,2)
		fmt.Printf("res3=%v",res3)//res3=7
	}

5. Recursion



The result is:
n=2
n=2
n=3
matters needing attention:
● when a function is executed, a new protected independent space (new function stack) is created
● the local variables of the function are independent and will not affect each other
● recursion must approach the condition of exiting recursion, otherwise it is wireless recursion
● when a function is executed or returns, it will be returned. The result will be returned to whoever calls it. At the same time, when the function is executed or returned, the function book will also be destroyed by the system

6. Precautions and details of function use

  1. The formal parameter list of a function can be multiple, and the return list can also be multiple

  2. The data types of formal parameter list and return value list can be value type and reference type

  3. The naming of the function follows the identifier naming specification. The first letter cannot be a number and the first letter is uppercase. The function can be used by this newspaper file and other package files. The first letter is lowercase and can only be used by this package file

  4. Variables in a function are local and do not take effect outside the function

  5. Basic data types and arrays are value passing by default, that is, value copying Modification within the function will not affect the original value

  6. If you want the variables inside the function to modify the variables outside the function (referring to the data type passed by value by default), you can pass in the address &, and operate the variables in the function in the form of pointers

  7. The go function does not support function overloading

  8. In go, a function is also a data type and can be assigned to a variable. Then the variable is a variable of function type, through which the function can be called

  9. Since the function is a data type, in go, the function can be used as a formal parameter and called

  10. To simplify data type definition, go supports custom function types
    ● basic syntax: Type: user defined data type name / / understanding: it is equivalent to an alias
    ● case: type myInt int int / / myInt is equivalent to int
    ● case: type mySum func(int,int)int / / in this case, mySum is equivalent to a function type func(int,int)int


  11. Support naming function return value

  12. Use_ Identifier, ignoring return value

  13. go supports variable parameters

7.init function

Each source file can contain an init function, which will be called by the go runtime framework before the main function is executed, that is, init will be called before the main function

Precautions and details:
● if a file contains global variable definition, init function and main function at the same time, the execution order is global variable definition - > init function - > main function

● the main function of init function is to complete some initialization
● if the imported packages have variable definitions and init, the execution order is

8. Anonymous function

go supports anonymous functions. Anonymous functions are functions without names. If we use a function only once, we can consider using anonymous functions. Anonymous functions can also be called multiple times

8.1 anonymous function usage 1

When calling an anonymous function, it is called directly. In this way, an anonymous function can only be called once

8.2 anonymous function usage 2

Assign an anonymous function to a variable (function variable), and then call the anonymous function through the variable

8.3 global anonymous function

If you assign an anonymous function to a global variable, the anonymous function becomes a global anonymous function

9. Closure

9.1 introduction to closure

A closure is a combination of a function and other related reference environments

Description and summary of the above code
● AddUpper is a function, and the returned data type is fun(int) int
● description of closure

○ an anonymous function is returned, but this anonymous function refers to n outside the function. Therefore, this anonymous function forms a whole with n to form a closure
● it can be understood that a closure is a class, a function is an operation, and n is a field Function and its use to n form a closure
● when we call f function repeatedly, because n is initialized once, it will be accumulated every time we call it
● modify the above code to deepen understanding

9.2 best practices for closures

● write a function makeSuffix(suffix string) to receive a file suffix (such as. jpg) and return a closure
● call closure to pass in a file name. If the file name has no specified suffix (such as. jpg), the file name will be returned jpg, if it already exists jpg suffix, the original file name is returned.
● closure is required
● strings.HasSuffix, which can determine whether a string has a specified suffix

● the returned anonymous function and the suffix variable of makeSuffix (suffix string) are combined into a closure, because the returned function refers to the suffix variable
● let's experience the benefits of closures. If we use traditional methods, we can easily realize this function, but the traditional methods need to pass in the suffix every time, such as jpg. Because closures can retain a value referenced last time, we can pass it in once for repeated use.

10. defer of function

10.1 why defer

In the function, programmers often create resources (such as database connection, file handle, lock, etc.) in order to release resources in time after the function is executed The designer of go provides a defer delay mechanism

10.2 precautions for defer

● when go executes a defer, it will not execute the defer statement immediately, but push the statement after defer into a stack, and then continue to execute the next statement of the function
● after the function is executed, take out the statements from the top of the defer stack for execution (first in, last out)
● when defer puts the statement on the stack, it will also copy the relevant values into the stack at the same time

10.3 best practices for defer

The main value of defer is that it can release the resources created by the function in time after the function is executed

explain:
● the common practice in golang programming is to execute defer file after creating resources, such as opening files, obtaining database links, or locking resources Close() defer connect. Close()
● after defer, you can continue to use and create resources
● after the function is completed, the system will take out the statements from the defer stack in turn and close the resources
● this mechanism is very simple, and programmers don't have to worry about when to turn off resources

11. Function parameter transfer method

2 Two delivery modes
● pass by value
● Reference passing
 In fact, whether it is value transfer or reference transfer, what is passed to the function is the copy of the variable. The difference is that the value transfer is the copy of the value, and the reference transfer is the copy of the address. Generally speaking, the address copy efficiency is high, because the amount of data is small, and the value copy determines the size of the copied data. The larger the data, the lower the efficiency.
● Value type:Basic data type int series, float series, bool, string ,Arrays and structures struct
● reference type:Pointer slice Slicing map,The Conduit chan,interface And so on are reference types


12. Variable scope

● variables declared / defined inside the function are called local variables, and the scope is limited to the inside of the function
● variables declared / defined outside the function are called global variables. The scope is valid in the whole package. If its initial letter is uppercase, the scope is valid in the whole program
● if the variable is in a code block, such as for/if, the scope of the variable is in the code block
● the compiler adopts the principle of proximity

13. String operation

package main
import (
	"fmt"
	"strconv"
	"strings"
)

func main(){

	//Counts the length of the string, in bytes len(str)
	golang The codes of are unified as utf-8 (ascii Character(Letters and numbers) Occupy one byte, and Chinese characters occupy three bytes)
	str := "hello north" 
	fmt.Println("str len=", len(str)) // 8


	str2 := "hello Beijing"
	//String traversal, while dealing with Chinese problems R: = [] run (STR)
	r := []rune(str2)
	for i := 0; i < len(r); i++ {
		fmt.Printf("character=%c\n", r[i])
	}
// Character = h
// Character = e
// Character = l
// Character = l
// Character = o
// Character = North
// Character = Beijing

	//String to integer: 	  n, err := strconv.Atoi("12")
	n, err := strconv.Atoi("123")
	if err != nil {
		fmt.Println("Conversion error", err)
	}else {
		fmt.Println("The result of conversion is", n)
	}

	//4) Integer to string STR = strconv Itoa(12345)
	str = strconv.Itoa(12345)
	fmt.Printf("str=%v, str=%T\n", str, str)

	//5) String to [] byte: VAR bytes = [] byte ("Hello go")
	var bytes = []byte("hello go")
	fmt.Printf("bytes=%v\n", bytes)//bytes=[104 101 108 108 111 32 103 111]

	//6)[]byte to string: str = string([]byte{97, 98, 99})
	str = string([]byte{97, 98, 99}) 
	fmt.Printf("str=%v\n", str)

	//Decimal to 2, 8, hexadecimal: STR = strconv Formatint (123, 2) returns the corresponding string
	str = strconv.FormatInt(123, 2)
	fmt.Printf("123 The corresponding binary is=%v\n", str)//123 corresponds to binary = 1111011
	str = strconv.FormatInt(123, 16)
	fmt.Printf("123 The corresponding hexadecimal is=%v\n", str)//123 corresponds to hex = 7b

	//Find whether the substring is in the specified string: strings Contains("seafood", "foo") //true
	b := strings.Contains("seafood", "mary")
	fmt.Printf("b=%v\n", b) 

	//Statistics: a string has several specified substrings: strings Count("ceheese", "e") //4
	num := strings.Count("ceheese", "e")
	fmt.Printf("num=%v\n", num)

	//10) Case insensitive string comparison (= = is case sensitive): FMT Println(strings.EqualFold("abc", "Abc")) // true

	b = strings.EqualFold("abc", "Abc")
	fmt.Printf("b=%v\n", b) //true

	fmt.Println("result","abc" == "Abc") // false / / case sensitive

	//11) Returns the index value of the substring at the first occurrence of the string. If - 1 is not returned: 
	//strings.Index("NLT_abc", "abc") // 4

	index := strings.Index("NLT_abcabcabc", "abc") // 4
	fmt.Printf("index=%v\n",index)

	//12) Returns the index of the substring at the last occurrence of the string,
	//If - 1 is not returned: strings LastIndex("go golang", "go")

	index = strings.LastIndex("go golang", "go") //3
	fmt.Printf("index=%v\n",index)

	//Replace the specified substring with another substring: strings Replace ("go go hello", "go", "go language", n) 
	//N can specify how many you want to replace. If n=-1, it means to replace all

	str2 = "go go hello"
	str = strings.Replace(str2, "go", "Beijing", -1)
	fmt.Printf("str=%v str2=%v\n", str, str2)

	//Split a string into an array of strings according to a specified character as a split identifier: 
	//strings.Split("hello,wrold,ok", ",")
	strArr := strings.Split("hello,wrold,ok", ",")
	for i := 0; i < len(strArr); i++ {
		fmt.Printf("str[%v]=%v\n", i, strArr[i])
	} 
	fmt.Printf("strArr=%v\n", strArr)

	//15) Convert the letters of the string to case: 
	//strings.ToLower("Go") // go strings.ToUpper("Go") // GO

	str = "goLang Hello"
	str = strings.ToLower(str) 
	str = strings.ToUpper(str) 
	fmt.Printf("str=%v\n", str) 

	//Remove the spaces on the left and right sides of the string: strings TrimSpace(" tn a lone gopher ntrn   ")
	str = strings.TrimSpace(" tn a lone gopher ntrn   ")
	fmt.Printf("str=%q\n", str)

	//17) Remove the characters specified on the left and right sides of the string: 
	//strings.Trim("! hello! ", " !")  // ["hello"] / / turn the left and right sides! And "" are removed
	str = strings.Trim("! he!llo! ", " !")
	fmt.Printf("str=%q\n", str)

	//20) Determine whether the string starts with the specified string: 
	//strings.HasPrefix("ftp://192.168.10.1", "ftp") // true

	b = strings.HasPrefix("ftp://192.168.10.1", "hsp") //true
	fmt.Printf("b=%v\n", b)
}

14. Time function

package main
import (
	"fmt"
	"time"
)

func main() {
	//Look at the use of date and time related functions and methods
	//1. Get the current time
	now := time.Now()
	fmt.Printf("now=%v now type=%T\n", now, now)

	//2. The date, hour, minute and second can be obtained through now
	fmt.Printf("year=%v\n", now.Year())
	fmt.Printf("month=%v\n", now.Month())
	fmt.Printf("month=%v\n", int(now.Month()))
	fmt.Printf("day=%v\n", now.Day())
	fmt.Printf("Time=%v\n", now.Hour())
	fmt.Printf("branch=%v\n", now.Minute())
	fmt.Printf("second=%v\n", now.Second())

	//Format date time

	fmt.Printf("Current date %d-%d-%d %d:%d:%d \n", now.Year(), 
	now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())

	dateStr := fmt.Sprintf("Current date %d-%d-%d %d:%d:%d \n", now.Year(), 
	now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())

	fmt.Printf("dateStr=%v\n", dateStr)

	//The second way to format the date and time
	fmt.Printf(now.Format("2006-01-02 15:04:05"))
	fmt.Println()
	fmt.Printf(now.Format("2006-01-02"))
	fmt.Println()
	fmt.Printf(now.Format("15:04:05"))
	fmt.Println()

	fmt.Printf(now.Format("2006"))
	fmt.Println()


	//If required, print a number every 1 second and exit when it reaches 100
	//Requirement 2: print a number every 0.1 seconds and exit when it reaches 100
	// i := 0
	// for {
	// 	i++
	// 	fmt.Println(i)
	// 	//Dormancy
	// 	//time.Sleep(time.Second)
	// 	time.Sleep(time.Millisecond * 100)
	// 	if i == 100 {
	// 		break
	// 	}
	// }

	//Use of Unix and UnixNano
	fmt.Printf("unix time stamp=%v unixnano time stamp=%v\n", now.Unix(), now.UnixNano())

}

Best practice: get timestamp

package main
import (
	"fmt"
	"time"
	"strconv"
)

func test03() {

	str := ""
	for i := 0; i < 100000; i++ {
		str += "hello" + strconv.Itoa(i)
	}
}

func main() {
	//Get the current unix timestamp before executing test03
	start := time.Now().Unix()
	test03()
	end := time.Now().Unix()
	fmt.Printf("implement test03()Time consuming%v second\n", end-start)
}

15. Built in function builtin

● len: used to find the length, such as string,array,slice,map,channel
● new: used to allocate memory, mainly used to allocate value types, such as int, float32, struct... Returns pointers

package main
import (
	"fmt"
)

func main() {

	num1 := 100
	fmt.Printf("num1 Type of%T , num1 Value of=%v , num1 Address of%v\n", num1, num1, &num1)

	num2 := new(int) // *int
	//Type of num2% t = > * int
	//Value of num2 = address 0xc04204c098 (this address is assigned by the system)
	//Address% v of num2 = address 0xc04206a020 (this address is assigned by the system)
	//Value pointed to by num2 = 100
	*num2  = 100
	fmt.Printf("num2 Type of%T , num2 Value of=%v , num2 Address of%v\n num2 This pointer, the value pointed to=%v", 
		num2, num2, &num2, *num2)
}


● make: used to allocate memory. It is mainly used to allocate reference types, such as channel, map and slice. See later

16. Error handling

16.1 example

	package main
	
	import (
		"fmt"
	)
	
	func test(){
		num1:=1
		num2:=0
		res:=num1/num2
		fmt.Println("res=",res)
	}
	
	func main(){
		fmt.Println("mian()Code continues 11111")
		test()
		fmt.Println("mian()Code continues 22222")
	}


If the project reports an error, the code will be executed before the error, and the code will not be executed after the error

16.2 handling errors

● go language pursues simplicity and elegance, so it does not support the traditional try... catch... finally
● processing methods introduced in go language: defer,panic,recover
● you can throw a public exception in go, then catch the exception in defer through recover, and then handle it normally

	package main
	
	import (
		"fmt"
	)
	
	func test(){
		//Use defer+recover to catch and handle exceptions
		defer func(){
			err := recover()//recover() is a built-in function that can catch exceptions
			if err != nil{
				fmt.Println("err=",err)
				fmt.Println("Continue execution...")
			}
		}()
		num1:=1
		num2:=0
		res:=num1/num2
		fmt.Println("res=",res)
	}
	
	func main(){
		fmt.Println("mian()Code continues 11111")
		test()
		fmt.Println("mian()Code continues 22222")
	}


Error handling, the code after the error continues to execute

16.3 custom error

● in the go program, user-defined errors are supported, using errors New and panic built-in functions
● errors.New("error description") will return a value of error type, indicating an error
● panic built-in function, which accepts a function of interface {} type (that is, any value) as a parameter You can receive variables of error type, output error messages, and exit the program

	package main
	
	import (
		"fmt"
		"errors"
	)
	
	//If the file name is not passed in correctly, a custom error is returned
	func readConf(name string)(err error){
		if name =="Config.ini" {
			//Correct, read
			return nil
		}else{
			//A custom error was returned
			return errors.New("Error reading file...")
		}
	}
	
	
	
	func main(){
		fmt.Println("Code continues 1111")
		err:=readConf("Config111.ini")
		if err !=nil{
			//If there is an error reading the file, output the error and terminate the program
			panic(err)
		}
		fmt.Println("Code continues 22222")
	}

Keywords: Go Back-end

Added by scraptoft on Sun, 23 Jan 2022 22:25:14 +0200