zoukankan      html  css  js  c++  java
  • Golang 基础 06 -- 函数 function

    目录

    @

    Tips

    • Go函数不支持 嵌套,重载 和 默认参数
    • 但支持以下特性: 无需声明原型,不定长度变参,多返回值,命名返回值参数,匿名函数,闭包
    • 定义函数使用关键字func,并且左大括号不能另起一行

    函数定义,不定长变参,传递值类型与引用类型

    func main(){
    	a,b := 1,2
    	//传入值类型的拷贝,(int,string),不会改变这里的值
    	B(a,b)
    	fmt.Println("a,b=",a,b)
    	fmt.Println(A())
    	ss := []int{5,6,7,8}
    	//传入的参数是slice,是数组地址的拷贝,会改变这里的值,类似指针
    	C(ss)
    	fmt.Println("ss=",ss)
    }
    func A()(int, int, int){
    	a,b,c := 1,2,3
    	return a,b,c
    }
    func B(s ...int){
    	//a是个slice,不定长变参,只能作为最后一个参数
    	s[0]=3
    	s[1]=4
    	fmt.Println("s=",s)
    }
    func C(s []int){
    	s[0] = 55
    	s[1] = 66
    	s[2] = 77
    	s[3] = 88
    	fmt.Println(s)
    }
    /*
    > Output:
    command-line-arguments
    s= [3 4]
    a,b= 1 2
    1 2 3
    [55 66 77 88]
    ss= [55 66 77 88]
    */
    
    • 值类型传递和引用类型传递都是拷贝,但是值类型是拷贝值,而引用类型是拷贝地址

    一切皆类型,包括函数

    • Go语言中,一切皆类型,函数也能作为一种类型使用
    func main(){
    	a := A
    	a()
    }
    func A(){
    	fmt.Println("Func A")
    }
    /*
    > Output:
    command-line-arguments
    Func A
    */
    

    匿名函数和闭包

    匿名函数

    -匿名函数不能是最外层函数

    func main(){
    	a := func(){
    		fmt.Println("Func A")
    	}
    	a()
    }
    func A(){
    	fmt.Println("Func A")
    }
    /*
    > Output:
    command-line-arguments
    Func A
    */
    

    闭包

    • 闭包函数的作用:返回一个匿名函数
    func main(){
    	f := closure(10)
    	fmt.Println(f(1))
    	fmt.Println(f(2))
    }
    func closure(x int) func(int) int {
    	fmt.Printf("outside %p
    ", &x)
    	return func(y int) int {
    		fmt.Printf("%p
    ", &x)
    		return x * y
    	}
    }
    /*
    > Output:
    command-line-arguments
    outside 0xc042054080
    0xc042054080
    10
    0xc042054080
    20
    */
    

    defer用法

    • defer的执行方式类似其他语言的析构函数,在函数体执行结束后,按照调用顺序的相反顺序执行(好像递归返回那样吧)
    • 就算函数发生了严重错误也会执行
    • 支持匿名函数的使用
    • 常用于资源清理,文件关闭,解锁以及记录时间等操作
    • 通过与匿名函数配合可以在return之后修改函数结果
    • 如果函数体内某个变量作为defer时匿名函数的参数,则在定义时就已经获得拷贝,否则则是引用某个变量的地址
    func main(){
    	fmt.Println("a")
    	defer fmt.Println("b")
    	defer fmt.Println("c")
    }
    //a,c,b
    
    • 把return语句看做赋值+返回RET指令两部分,defer是插入在中间的,并且注意defer里面的函数操作的是返回值还是别的变量,匿名函数的参数是值传递还是引用传递,值传递就不会改变返回值啦
    • 参照大佬解析
    • 注意:defer后面定义的匿名函数要在最后加上(参数)
    func main(){
    	for i:=0; i<3; i++ {
    		defer func() {
    			fmt.Println(i)
    			}()
    	}
    	fmt.Println("a")
    	defer fmt.Println("b")
    	defer fmt.Println("c")
    }
    /*
    > Output:
    command-line-arguments
    a
    c
    b
    3
    3
    3
    */
    

    panic 与 recover,错误处理机制

    • Go没有异常机制,但是panic/recover模式来处理错误
    • panic可以在任何地方引发,但是recover只有在defer调用的函数
    func main(){
    	A()
    	B()
    	C()
    }
    func A() {
    	fmt.Println("Func A")
    }
    //defer要放在panic前面才有效,程序遇到panic就停了,所以要在这之前先注册defer的函数,且panic语句也不会执行了
    func B() {
    	defer func() {
    		if err:=recover(); err!=nil{
    			fmt.Println("recover in B")
    		}
    	}()
    	panic("panic in B")
    }
    func C() {
    	fmt.Println("Func C")
    }
    /*
    > Output:
    command-line-arguments
    Func A
    recover in B
    Func C
    */
    

    综合例子

    func main(){
    	var fs = [4]func(){}
    	for i := 0; i<4; i++ {
    	//值拷贝i+defer先进后出的输出
    		defer fmt.Println("defer i= ",i)
    		//引用拷贝(匿名函数没有参数,引用的i是外层的地址拷贝,为4)+defer
    		defer func() {fmt.Println("defer_closure i= ",i)}()
    		//引用拷贝(匿名函数没有参数,引用的i是外层的地址拷贝,为4)
    		fs[i] = func(){	fmt.Println("closure i= ",i)}
    	}
    	for _,f := range fs {
    		f()
    	}
    }
    /*
    > Output:
    command-line-arguments
    closure i=  4
    closure i=  4
    closure i=  4
    closure i=  4
    defer_closure i=  4
    defer i=  3
    defer_closure i=  4
    defer i=  2
    defer_closure i=  4
    defer i=  1
    defer_closure i=  4
    defer i=  0
    */
    
  • 相关阅读:
    springboot自定义对象参数
    mybatis学习之查询条件构造器
    C#的Abstract和Virtual
    ducker的网络介绍
    docker启动Tomcat报错404解决
    EF框架报错:System.Data.Entity.Internal.AppConfig的类型初始值设定项引发异常
    docker的运行过程
    html的video控件使用
    EF中lambda表达式实现LIKE模糊查询
    nginx和Tomcat的区别
  • 原文地址:https://www.cnblogs.com/leafs99/p/golang_basic_06.html
Copyright © 2011-2022 走看看