【Go基础】函数

函数


基本介绍

基础格式形如:

func function_name ([parameter list]) [return_types] {

​ 函数体

}

  • func:function的缩写,是定义函数的关键字。
  • function_name:函数名。
  • [parameter_lists]:函数列表,可以有0个或多个。
  • [return_types]:返回值类型,可以有0个或多个返回值。
  • 示例一:基操
import "fmt"

func main() {

	var v = add(1, 2)
	fmt.Println("v = ", v) // 输出:a2 =  10
}

func add(a int, b int) int {
	return a + b       
}
  • 示例二:如果相邻的参数类型相同,则可以采用简便写法
import (
	"fmt"
	"strconv"
)

func main() {
	fmt.Println(hello(1, 2, "Justry", "Deng")) // 输出:3JustryDeng
}

func hello(a, b int, c, d string) string {
	// strconv.Itoa的作用是:将int转换为tring
	return strconv.Itoa(a+b) + c + d
}
  • 示例三:多返回值
import (
	"fmt"
)

func main() {
	v1, v2 := hello(0, 0)
	fmt.Println(v1, "\t", v2) // 输出:100 	 -100
}

func hello(a, b int) (int, int) {
	return1 := a + 100
	return2 := b - 100
	return return1, return2
}
  • 示例四:无返回值
import (
	"fmt"
)

func main() {
	hello("邓沙利文")
}

func hello(name string) {
	fmt.Println("hello " + name) // 输出:hello 邓沙利文
}
  • 示例五:形参传递变量的地址(,在方法内部可修改外部变量的值)

    提示:对照组是没使用地址变量前的效果,实验组是使用地址变量后的效果

    • 对照组

      import (
      	"fmt"
      )
      
      func main() {
      	a := 1
      	add(a)
      	fmt.Println("调用add后,值为", a) // 输出:调用add后,值为 1
      }
      
      func add(v int) {
      	v++
      	fmt.Println("add方法内部,值为", v) // 输出:add方法内部,值为 2
      }
      
    • 实验组

      import (
      	"fmt"
      )
      
      /**
       * 提示:值变量前加上&, 即代表值变量的地址
       *      地址变量前加上*, 即代表地址变量的地址值
       */
      func main() {
      	a := 1
      	add(&a)
      	fmt.Println("调用add后,值为", a) // 输出:调用add后,值为 2
      }
      
      func add(v *int) {
      	*v++
      	fmt.Println("add方法内部,值为", *v) // 输出:add方法内部,值为 2
      }
      

注:在值变量前加上&,可以得到值变量的地址;在地址变量前加上*,可代表内存单元,即:指向该地址的值变量的值

匿名函数

匿名函数即没有函数名字的函数

  • 示例一:基操
import (
	"fmt"
)

func main() {
	a := func(v int) int {
		return v + 1
	}(99)
	fmt.Println("a = ", a) // 输出:a =  100
}

提示:匿名函数体后,带小括号才代表该匿名函数被调用

  • 示例二:匿名函数作为参数
import (
	"fmt"
)

func main() {
	a, b := 300, 500
	fmt.Println("a + b = ", addOrSub(a, b, add)) // 输出:a + b =  800
	fmt.Println("a - b = ", addOrSub(a, b, sub)) // 输出:a - b =  -200
}

func add(a, b int) int {
	return a + b
}

func sub(a, b int) int {
	return a - b
}

/**
 * 其中变量f的类型是函数 func(v1, v2 int) int, 即:所有满足func(v1, v2 int) int格式要求的函数,都可以作为该处的参数
 */
func addOrSub(a, b int, f func(v1, v2 int) int) int {
	return f(a, b)
}

函数闭包

所谓闭包就是在函数内部,可以读取父函数的变量

  • 代码示例:
func getSequence() func() int {
	i := 0
	return func() int {
		i++
		return i
	}
}
  • 说明:getSequence()中的内部结构,i在该函数内部定义,属于局部变量,但是在返回的匿名函数中对这个i进行了引用(闭包),并且把这个i进行了返回。每当getSequence()被调用时实际得到的是以func() int为原型的匿名函数,由于该匿名函数对i的引用一直存在,因此本来是临时变量的i在getSequence()返回后并不会被释放,内存分析如图:
    在这里插入图片描述

  • 这个getSequence函数的作用很有意思,在通过调用getSequence得到的匿名函数每次调用时,都会促使i的值自增,这样就得到了类似数据库中的自增序列那样的功能,示例:

    import (
    	"fmt"
    )
    
    func main() {
    	nextnumber := getSequence()
    	fmt.Println(nextnumber()) // 输出:1
    	fmt.Println(nextnumber()) // 输出:2
    	fmt.Println(nextnumber()) // 输出:3
    }
    
    func getSequence() func() int {
    	i := 0
    	return func() int {
    		i++
    		return i
    	}
    }
    
  • 加深理解:如果再用一个f := getSequence(),fnextnumber交替使用,彼此会互相影响吗?答案是不会。虽然getSequence()被调用时i是不释放的,但是不同的getSequence()调用时对应的i的内存地址是不同的,也就是说2此调用会产生2个独立的i,不会彼此影响,内存分析如图:
    在这里插入图片描述

  • 用代码验证一下:

    import (
    	"fmt"
    )
    
    func main() {
    	nextnumber := getSequence()
    	fmt.Println(nextnumber()) // 输出:1
    	fmt.Println(nextnumber()) // 输出:2
    	fmt.Println(nextnumber()) // 输出:3
    
    	f := getSequence()
    	fmt.Println(f()) // 输出:1
    	fmt.Println(f()) // 输出:2
    	fmt.Println(f()) // 输出:3
    }
    
    func getSequence() func() int {
    	i := 0
    	return func() int {
    		i++
    		return i
    	}
    }
    


^_^ 整理自《Go语言区块链应用开发从入门到精通》高野 编著

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值