函数,包及错误处理

#### Go 函数,包(一)
***天行健,两仪遵道恒长***
##### 函数
是为了完成某一功能的程序语句的集合, 在Go 中函数分为自定义函数,系统函数
函数语法:
func 函数名(形参列表)(返回值列表){
函数语句
return 返回值列表
}
案例:
package main

import "fmt"

func add(a,b int) int{
   return a + b
}
func main() {
   var sum int
   sum = add(10,20)
   fmt.Println(sum)
}

  


##### 包
在开发中, 我们往往需要去调用其它文件中定义的函数;包的本质实际上就是创建不同的文件夹,来存放程序文件;
go 的每一个程序文件都属于一个包,也可以说go 是以包的形式管理文件及项目目录结构;
###### 包的作用:
1. 区分相同名字的函数,变量等标识符;
2. 可以很好的管理项目;
3. 控制函数,变量等访问函数,也就是作用域;

package main

import (
   "ReadingNovels/src/utils"
   "fmt"
)

func main() {
   var sum int
   sum = utils.Add(10,20)
   fmt.Println(sum)
}

  


包的注意事项:
在给一个文件打包时,该包对应一个文件夹,比如utils 文件对应的包名就是utils,文件的包名通常和文件所在的文件夹名一致,一般为小写字母;
当一个文件夹要使用其它包函数或变量时,需要先引入包
1. 引入方式1: import "包名"
2. 引入方式2: import (
"包名"
"包名"
)
3. package 指令必须在第一行
4. 如果希望其它包访问本包中的函数或变量,***函数名或变量需要首字母大写***
5. 访问时语法为包名.函数名或包名.变量名
6. 如果名包较长,可以给包取别名: 取完别名后,原来的包名将不能使用,必须使用新的包名;
7. 在同一包下不能有相同的函数名和全局变量名
8. 如果要编译成一个可执行程序,需要将这个包声明为main, 如果是一个库,包名可以自定义;
package main
import (
   util "ReadingNovels/src/utils"
   "fmt"
)

  


---
###### 函数调用机制
package main

import (
   "fmt"
)
func add(a int){
   a += 10
   fmt.Println(a) // 11
}

func main() {
   var sum = 1
   add(sum)
   fmt.Println(sum)//1 
}

  


说明:
1. 在调用一个函数时,会给该函数分配一个新的空间,编译器会通过自身的处理让这个新的空间与其它空间分开;
2. 在每个函数对应的空间中,数据空间是独立的,不是混淆;
3. 当一个函数调用完毕后,程序会销毁这个函数对应的空间;
4. 对于上述例子: add 函数内部值变了, main 函数中值未改变
---
###### return
Go 中函数支持返回多个值
func 函数名(形参列表)(返回值列表){
函数体
return 返回值列表
}
1. 如果返回多个值,在接收时希望忽略某个值,使用"_"符号表示占位忽略;
2. 如果返回值只有一个,返回值列表可以不需要();
package main

import (
   "fmt"
)
func calc(a ,b int)(int,int){
   return a+b,a-b
}

func main() {
   var a = 1
   var b = 3
   sum,sub := calc(a,b)
   fmt.Println(sum,sub) //4,-2
   // 如果希望忽略某个值可以使用_
   sum,_ = calc(a,b)
}

  


---
###### 递归函数
如果一个函数在函数体内又调用了本身,我们称这个函数为递归函数;
import "fmt"

func recurse(n int){
   if n > 2 {
      n--
      recurse(n)
      fmt.Println(n)
   }
}
func main() {
   recurse(5)
}

  


递归函数需要遵守的重要原则:
1. 递归必须向退出递归条件逼近, 否则就是无限递归;
2. 当一个函数执行完毕或者遇到return 就会返回,遵守谁调用就将结果返回给谁, 同时当函数执行完毕或者返回时,函数本身也会被系统销毁;
package main

import "fmt"

func recurse(n int)int{
   if n ==1 || n==2 {
      return 1
   }else {
      return recurse(n-1) + recurse(n-2)
   }
}
func main() {
   fmt.Println(recurse(8))
}

  


---
函数使用注意事项和细节
1. 函数的形参列表可以是多个,返回值列表也可以是多个;
2. 形参列表和返回值列表的数据类型可以是值类型,也可以是引用类型;
3. 函数的命名遵守标识符命名规范,首字母大写表示该函数可以被本包文件和其它包文件使用,首字母小写表示只能被本包文件使用;
4. 函数中的变量是局部的,函数外不生效;
5. 基本数据类型和数组默认都是值传递: 进行值拷贝,在函数内修改不影响原来的值;
6. 如果默认的数据类型希望在函数内修改,可以传入变量的地址&,函数内以指针的方式 操作变量,类似引用;
7. Go 中函数不支持函数重载;
8. ***Go 中函数也是一种数据类型***,可以将函数赋值给一个变量,可以通过该变量对函数进行调用 ;
9. 函数可以做为形参传入函数,并用调用;
10. 函数支持对返回值命名;
11. 支持可变参数;
package main

import "fmt"

func test01(){
   var a int
   fmt.Println(a) // 0
}
func test02(n int){
   n += 10
   fmt.Println(n) // 10
}
func test03(n *int){
   *n += 10
   fmt.Println(*n) // 11
}
func test04(n func()) {
   n()
}
func test05(n int)(res int){
   res += n
   return
}
func test06(a ...int){
   var count int
   for _,v := range a {
      count += v
   }
   fmt.Println(count)
}
func main(){
   // fmt.Println(a)
   // 1. 函数是局部的,test01函数外没有变量a
   // 2. 基本数据类型是值传递, 在函数内修改不影响原来的值
   var b int
   test02(b)
   fmt.Println(b) // 0
   // 3. 基本数据类型希望在函数内修改,可以传变量的地址;
   var c  = 1
   test03(&c)
   fmt.Println(c) // 11
   // 4. 函数也是一种数据类型,可以赋值给一个变量
   var d func()
   d = test01
   d() // 0
   // 5. 函数可以作为形参传入函数
   test04(d) // 0
   // 6. 函数支持对返回值命名
   res := test05(10) // 10
   fmt.Println(res)
   // 7. 函数支持可变参数
   test06(1,2,3,4,5,6) // 21
   // 切片可以作为可参数传入函数,后面学习到切片时会详细介绍
   var f  = []int{1,2,3,4,5,6}
   test06(f...) //21
}

  个人微信公众号上有最近文章,欢迎大家关注,一同交流学习;



原文地址:https://www.cnblogs.com/Mail-maomao/p/11411754.html