Golang学习(八) init函数、匿名函数、闭包

一、init函数

init初始化函数,会在main函数执行前执行,如果import了其他的包中包含init函数

那么他会优先去扫描导入包中的init函数并执行

案例1 

package main

import "fmt"

func init() {
	fmt.Println("test main init")
}


func main(){
   fmt.Println("echo main")
}

返回

test main init
echo main

#init函数会在main之前执行

案例2

vi utils/utils.go

package utils

import "fmt"

func init() {
	fmt.Println("utils test init")
}
func Test()  {
	fmt.Println("test")
}

vi main/main.go

package main

import (
	"fmt"
	"test/utils"

)

func init() {
	fmt.Println("main test init")
}
func main(){
    utils.Test()
}

返回

utils test init     #先去执行了要导入的包的init
main test init      #然后执行了main的init函数,所有init执行完毕后,执行main函数
test                #通过main函数调用utils包的test函数,输出test

init函数细节

如果一个文件同时包含"全局变量"、"init函数"、 "main 函数"

#则执行的顺序是
  全局变量定义--> init函数--> main 函数

二、 匿名函数

当我们只希望一个函数只需要执行一次时,就可以使用匿名函数,当然匿名函数也可以使用多次

 语法格式

func (形参传入) 返回值列表 {

     代码块

	}(实参)



#和正常的函数类似,只不过去除了函数的名称
#因为没有函数名,无法调用传参,所以直接在{}后面使用括号()进行参数传递

#例如
func (n1 int,n2 int) int{
		return n1 + n2
	}(10,20)

案例1   在定义匿名函数时直接使用

package main

import "fmt"

func main()  {
	//在定义匿名函数时直接使用.这种方式匿名函数只能调用一次
    //通过匿名函数,我们指定传入了10、20的值给n1、n2
    //通过{} 内返回值是n1+n2的和,返回值类型是int
    //通过:= 类型推导  赋值给res1 

	res1 := func (n1 int,n2 int) int{
		return n1 + n2
	}(10,20)

    
	fmt.Println(res1)       //这样的匿名函数只能使用一次,用作临时运算
    

}

案例2 将匿名函数写入成一个变量

上面的的方法是给匿名函数直接提供参数进行运算,我们可以把匿名函数定义为一个变量 多次使用

package main

import "fmt"

func main()  {


	a := func (n1 int,n2 int) int{   //我们将这个匿名函数定义给了a变量 (没有设置参数)
		return n1 + n2
	}

	res2 := a(10,20)           //此时a变量就可以看作是一个独立的函数,
                               //通过a()来调用这个函数,可以多次调用
	fmt.Println(res2)


}

案例3 全局匿名函数

package main

import "fmt"

var (
    //Fun1 是全局变量,我们将一个匿名函数赋给这个变量,他就可以在整个程序中使用了
    //如果首字母大小,那么就可以在不同的包中调用该匿名函数
    Fun1 = func (n1 int,n2 int) int {
        return n1 * n2
    }
)

func main()  {
    
    res4 := Fun1(10,20)   //调用匿名函数
    fmt.Println(res4)
}

三、闭包

发现一篇写的很详细的,转一下哈 O(∩_∩)O

Golang中闭包的理解_Erick Lv的笔记-CSDN博客_golang 闭包

案例

package main

import "fmt"

var f = func(int) {}    //定义一个匿名函数的变量

func main() {

	f = func(i int) {    //f可以被任何输入一个整型,并且无返回值的匿名函数给赋值
		fmt.Println(i)
	}
	f(2)

	f = func(i int) {
		fmt.Println(i * i * i)
	}
	f(2)
}

匿名函数有动态创建的特性,使得匿名函数不用通过参数传递的方式,就可以直接引用外部的变量。类似常规函数引用全局变量

package main

import "fmt"

func main() {
	n := 0          //定义普通变量

	f := func() int {   //将匿名函数封装为变量
		n += 1      //在匿名函数中调用匿名函数外部的变量
                    //运算会修改外部变量的值
		return n
	}
	fmt.Println(f())  //f()调用匿名函数 去做n += 1的操作
	fmt.Println(f())  //通过return n  会将匿名函数计算完的值返回给 n变量
}

 返回

1
2

说明

n := 0
f := func() int {
	n += 1
	return n
}


//上述代码就是一个闭包,类比于常规函数+全局变量+包。
//f不仅仅是存储了一个函数的返回值,它同时存储了一个闭包的状态。

闭包作为函数返回值

匿名函数作为返回值,不如理解理解为闭包作为函数的返回值,

 案例1 返回值

package main

import "fmt"

func Increase() func() int {
	n := 0
	ss := func() int {
		n++
		return n
	}
	return ss
}

func main() {
	in := Increase()     //闭包被返回赋予一个同类型的变量时,同时赋值的是整个闭包的状态
						//这个状态会一直存在外部被赋值的变量in中
						//直到in被消耗,整个闭包也被销毁
	fmt.Println(in())
	fmt.Println(in())
}

 返回

1
2

案例2 传入参数的返回值

package main
import "fmt"

func AddUpper() func (int) int {
	var n int  = 10

	ss := func (x int) int {
		n = n + x
		return n
	}

    return ss
}

func main()  {

	f := AddUpper()      

	fmt.Println(f(1))    
	fmt.Println(f(2))

}

返回

11
13

综合案例

编写一个程序,要求如下
1. 编写一个函数makeSuffix(suffix string) 可以接受一个文件后缀名(比如.jpg),并返回一个闭包
2. 调用闭包,可以传入一个文件名,如果文件没有指定的后缀
    (比如.jpg)   则返回文件名.jpg,如果已有.jpg后缀,则返回源文件名

3. 要求使用闭包的方式完成

4. strings.HasSuffix(变量,后缀名)  #该函数可以判断字符串是否有指定的后缀

案例

package main

import (
	"fmt"
	"strings"
)


func makeSuffix(suffix string) func(string) string{

	return func(name string) string {
		if strings.HasSuffix(name,suffix) == false {  //strings.HasSuffix判断name字符串的后缀,是否是.jpg
			return name + suffix                      //如果不是,则结尾添加.jpg
		}
		return name      //如果是,则直接返回该名称
	}

}
func main()  {
	f := makeSuffix(".jpg")
	
	//调用闭包,传入参数到name变量
	fmt.Println("文件名处理好=",f("winter"))
	fmt.Println("文件名处理好=",f("bird.jpg"))
}

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