go从0到1项目实战体系四:函数

1. 函数:

. 声明:
   func 函数名字 (参数列表) (返回值列表){}. 举例:
   func add() {}
   func add(a int , b int) int {}
   func add(a int , b int) (int, int) {}. 特点:
   a. 不支持重载,一个包不能有两个名字一样的函数.
   b. 函数也是一种类型,一个函数可以赋值给变量(这个变量是一个指针指向函数地址).
   c. 匿名函数
   d. 多返回值
   e. type定义新的类型:type addFunc func(int, int) int  => 表示函数也是一种类型

④. 函数参数传递方式:
   a. 值传递
   b. 引用传递
   c. 值传递、引用传递,传递给函数的都是变量的副本.值传递是值的拷贝,引用传递是地址(8个字节)的拷贝.
   d. 一般来说,地址拷贝更为高效.值拷贝取决于拷贝的对象大小,对象越大,则性能越低.
   e. map、slice、chan、指针、interface默认以引用的方式传递.. 命名返回值的名字:
   func calc(a, b int) (sum int, avg int) {
      sum = a + b
      avg = (a +b) / 2
      return
   }. _标识符,用来忽略返回值.
   a, _ = add()
   _, a = add(). 可变参数:
   func add(arg…int) int {}              // 0个或多个参数
   func add(a int, arg…int) int {}       // 1个或多个参数,a是固定参数(可以有多个固定参数)
   a. arg是一个slice(切片).
   b. 通过arg[index]依次访问所有参数.
   c. 通过len(arg)来判断传递参数的个数.

2 defer:

(1). 概念:

. 当函数返回时,执行defer语句.因此,可以用来做资源清理.. 多个defer语句,按先进后出的方式执行(最晚的先执行).. defer语句中的变量,defer声明时就决定了.. 举例:
   var a int = 111
   defer fmt.Println(a)      // 第3执行,打印值为111.在defer定义时,是什么值就是什么值.跟后面没关系.
   defer fmt.Println("333")  // 第2执行,因为先进后出,先入栈后出.
   a = 222
   fmt.Println(a)            // 第1执行
   结果:
   222
   333
   111

(2). 用途:

. 关闭文件句柄:
   file := open(filename)
   defer file.Close()
   // 文件操作. 锁资源释放:
   mc.Lock()
   defer mc.Unlock()
   // 其他操作. 数据库连接释放:
   conn := openDatabase()
   defer conn.Close()
   // 其他操作

3. 内置函数:

①. close:
   主要用来关闭channel.

②. len:
   用来求长度,如string、array、slice、map、channel.

③. new:
   用来分配内存(值类型),如int、struct.返回的是指针.
   a := new(int)         // 返回一个内存地址
   *a = 100

④. make:
   用来分配内存(引用类型),如chan、map、slice.

⑤. append:
   用来追加元素到数组、slice中.

⑥. panic和recover:
   用来做错误处理.
   defer func() {
      if err := recover(); err != nil {
         fmt.Println(err)
      }
   }()            // 匿名函数自调用

   func initConfig() (err error) {
      return errors.New("init config failed")
   }
   func main() {
      err := initConfig()
      if err != nil {
         panic(err)
      }
   }

3.1 new与make的区别:

. new:
   a. new一个[]int的切片                 => 第一行
   b. new返回一个指向切片的指针(*[]int)  => 第二行
   c. 这个地址指向一个实际的切片         => 第三行

②. make返回不是一个指针,就是一个切片.. 举例:
   c := new([]int)
	fmt.Println(c)             // &[],返回指向切片的指针.
	d := make([]int, 3)
	fmt.Println(d)             // [0 0 0],返回一个切片
   // 如果没有这句会报错:panic: runtime error: index out of range.
   // 因为new的时候,指针指向一个空的slice,slice没有初始化.
   *c = make([]int, 5)
   (*c)[0] = 1                // 因为是指针,加*号
	d[0] = 2

4. 递归函数:

斐波那契数(前两个数相加等于后一个数):

func fab(n int) int {
	if n <= 1 {
		return 1
	}
	return fab(n-1) + fab(n-2)
}
func main() {
	for i := 0; i < 10; i++ {
		n := fab(i)
		fmt.Println(n)
	}
}

5. 闭包:

一个函数和与其相关的引用环境组合而成的实体.

func Adder() func(int) int {          // 返回一个函数func(int) int
   var x int
   return func(d int) int {           // 这里必须与定义的返回函数一致
      x += d
      return x
   } 
}
func main() {
   var f = Adder()
   fmt.Print(f(1), " - ")             // 1
   fmt.Print(f(20), " - ")            // 21
   fmt.Print(f(300))                  // 321
}

你可能感兴趣的:(golang,开发语言,后端)