使用函数
函数就是将一段输入数据转换为输出数据的公用代码块
函数示例
package main import "fmt" func slice_sum(arr []int) int { sum := 0 for _, elem := range arr { sum += elem } return sum } func main() { var arr1 = []int{1, 3, 2, 3, 2} var arr2 = []int{3, 2, 3, 1, 6, 4, 8, 9} fmt.Println(slice_sum(arr1)) fmt.Println(slice_sum(arr2)) }
1、命名返回值,即为返回值预先定义一个名称,最后直接一个return,就可以将预定义的返回值全部返回
重新定义上面的求和函数,示例代码如下
func slice_sum(arr []int) (sum int) { sum = 0 for _, elem := range arr { sum += elem } return }
2、函数多返回值,即同时返回多个值
package main import "fmt" func slice_sum(arr []int) (int, float64) { sum := 0 //注意是float64类型 avg := 0.0 for _, elem := range arr { sum += elem } avg = float64(sum) / float64(len(arr)) return sum, avg } func main() { var arr = []int{3, 2, 3, 1, 6, 4, 8, 9} fmt.Println(slice_sum(arr)) }
也可以用预命名返回值名称方式编写函数代码
func slice_sum(arr []int) (sum int, avg float64) { sum = 0 //注意是float64类型 avg = 0.0 for _, elem := range arr { sum += elem } avg = float64(sum) / float64(len(arr)) return }
3、变长参数;变长参数列表内参数类型都是相同的、可变长参数只能是函数的最后一个参数
package main import "fmt" func sum(base int, arr ...int) int { sum := base for _, val := range arr { sum += val } return sum } func main() { fmt.Println(sum(100, 2, 3, 4)) }
变长参数的函数传入切片,如下,注意切片后面的三个点
func main() { var arr = []int{2, 3, 4} fmt.Println(sum(100, arr...)) }
4、闭包函数:简单理解就是在函数内,定义一个返回函数的变量,可以通过该变量执行其定义的函数,并且在变量函数内可以使用或改变外部函数的变量值
package main import "fmt" func main() { var base = 300 sum := func(arr ...int) int { total_sum := base for _, val := range arr { total_sum += val } return total_sum } arr := []int{1, 2, 3, 4} fmt.Println(sum(arr...)) }
闭包示例:生成偶数序列,输出 0,2,4
package main import "fmt" func createEvenGenerator() func() uint { i := uint(0) return func() (retVal uint) { retVal = i i += 2 return } } func main() { nextEven := createEvenGenerator() fmt.Println(nextEven()) fmt.Println(nextEven()) fmt.Println(nextEven()) }
5、递归函数,函数内重复调用自己,直到遇到出口,如阶乘函数,出口就是当x=0,示例如下
package main import "fmt" func factorial(x uint) uint { if x == 0 { return 1 } return x * factorial(x-1) } func main() { fmt.Println(factorial(5)) }
斐波拉切数列,出口是n=1和n=2
package main import "fmt" func fibonacci(n int) int { var retVal = 0 if n == 1 { retVal = 1 } else if n == 2 { retVal = 2 } else { retVal = fibonacci(n-2) + fibonacci(n-1) } return retVal } func main() { fmt.Println(fibonacci(5)) }
6、异常处理
1)defer标注,不论在函数中的什么位置,都是最后执行,即使中间有异常,也会最后执行defer标识的代码,如下面例子,虽然second函数在first函数前面,但是最后执行
package main import "fmt" func first() { fmt.Println("first func run") } func second() { fmt.Println("second func run") } func main() { defer second() first() }
defer用于资源释放的案例
package main import ( "bufio" "fmt" "os" "strings" ) func main() { fname := "D:\\test.txt" f, err := os.Open(fname) defer f.Close() if err != nil { os.Exit(1) } bReader := bufio.NewReader(f) for { line, ok := bReader.ReadString('\n') if ok != nil { break } fmt.Println(strings.Trim(line, "\r\n")) } }
2)、panic触发异常,在defer中使用recover函数接收异常信息,recover只能在defer中才有效,因为异常抛出后,下面的代码不会执行,defer会在最后执行
package main import ( "fmt" ) func main() { defer func() { msg := recover() fmt.Println(msg) }() fmt.Println("I am walking and singing...") panic("It starts to rain cats and dogs") }
结果图