在go语言中,函数的基本组成为:关键字func、函数名、参数列表、返回值、函数体和返回语句数组
定义一个最简单的加法函数闭包
func Add(a int,b int)(ret int,err error){ if a < 0 || b < 0{ err = errors.New("这个函数只支持两个非负数的数字相加") return } return a + b,nil }
若是参数列表中若干相邻的参数类型是相同的话,好比上述例子中的a和b,则能够在参数列表中省略前面的类型声明,例如:函数
func Add(a,b int)(ret int,err error){ // ... }
若是返回值列表中多个返回值的类型相同,也能够用一样的方式合并code
若是函数只有一个返回值,也能够这样写:对象
func Add(a,b int) int{ // ... }
函数调用很是方便,只须要事先导入了该函数所在的包,就能够直接调用了,在go语言中,对函数命名有必定要求,只有大写开头的字母才能够被其余包调用,小写字母开头的函数只能在本包被调用作用域
例:假设Add函数在func1中开发
package main import ( "fmt" //导入包 "functions/func1" ) func main() { a := 1 b := 2 // 经过包名调用函数 ret,err := func1.Add(a,b) fmt.Println(ret,err) }
不定参数是值函数传入的参数个数为不定数量。io
func main(){ // myfunc函数能够接收任意个int类型的参数 myfunc(1,2,3,4,5,6,7,8) } // ... 表示不定参数 func myfunc(args ...int){ for _,arg := range args { fmt.Println(arg) } }
...type格式的类型只能做为函数的参数类型存在,而且必须是最后一个参数。。它是一
个语法糖(syntactic sugar),即这种语法对语言的功能并无影响for循环
从内部实现机理上来讲,类型...type本质上是一个数组切片,也就是[]type,这也是为
什么上面的参数args能够用for循环来得到每一个传入的参数。
假如没有...type这样的语法糖,开发者将不得不这么写:function
func myfunc2(args []int) { for _, arg := range args { fmt.Println(arg) } }
从函数的实现角度来看,这没有任何影响,该怎么写就怎么写。但从调用方来讲,情形则完
全不一样:
myfunc2([]int{1, 3, 7, 13})
func myfunc(args ...interface{}){ // ... }
用interface{}传递任意类型数据是go语言的惯例用法
匿名函数由一个不带函数名的函数声明和函数体组成,如:
func(a,b int) bool { return a * b }
匿名函数能够直接赋值给一个变量或者直接执行
// 赋值给一个变量 f := func(a,b int) int { return a * b } // 直接执行 func(a,b int) bool { return a * b }(1,2)
func main() { var j int = 5 //一个函数的返回值是一个函数的执行 a := func()(func()) { var i int = 10 return func() { fmt.Printf("i,j : %d %d \n",i,j) } }() a() j *= 2 a() }