2019独角兽企业重金招聘Python工程师标准>>>
- go语言中函数重载是不允许的
- 函数可以以声明的方式被使用,作为一个函数类型:
type binOp func(int, int) int
-
函数可以作为一个变量进行传递,当两个函数变量进行比较时,当且仅当两个函数相同,或者都为nil时才相等
-
目前go语言中没有泛型的概念,但是可以通过接口,特别是空接口与type switch或反射来实现类似的功能
-
任何一个有返回值的函数都必须以return或panic结尾
-
函数调用时,其参数的传递都是按值传递的,也就是说参数接收到的是传递的值的副本,有的时候我们可以传递引用的副本给参数如
Function(&variable)
,这个时候参数得到的是一个指针的拷贝,但是通过这个指针存储的值我们也可以操作原始对象的数据 -
几乎在任何情况下,传递指针的消耗都比传递副本来得少
-
函数的返回值可以有多个,对于返回值的声明,可以只在函数上声明返回值的类型,也可以为每个返回值设置一个名称。如果为返回值设置了名称,需要注意的是,该返回值在进入函数时就相当于声明了一个局部变量,也就是说在函数内不需要再声明该变量,而可以直接赋值使用,并且这种情况下,函数的return后也可以不接任何的参数,而只需要写一个return即可,但是为了代码的可读性,强烈建议这种情况也把返回值给写上。
// 不具名返回值
func getX2AndX3(input int) (int, int) {
return 2 * input, 3 * input
}
// 具名返回值
func getX2AndX3_2(input int) (x2, x3 int) {
x2 = 2 * input
x3 = 3 * input
return
}
-
尽量使用命名返回值,这会使代码更清晰,更简短,同时更加容易读懂
-
对于函数返回值,可以使用空白符
_
来将某个或某几个不需要的返回值给忽略掉 -
变长参数的传递指的是在参数列表的最后一位上使用诸如
arg ...type
的形式传递的参数,变长参数的函数声明形式如下:
func myFunc(a, b string, arg ...int) {}
- 变长参数本质上就是一个slice,需要注意的是,如果需要将一个slice当做变长参数传递给函数,那么该参数后必须加上
...
,如:
s := []int{3, 1, 4, 9, 7, 1}
result = min(s...)
fmt.Printf("min num is %d\n", result)
- type switch结构
func typecheck(val ...interface{}) {
for _, v := range val {
switch v.(type) {
case int:
case float64:
case string:
default:
}
}
}
- defer关键字允许我们推迟到函数返回之前(或任意位置执行return语句之后)一刻才执行某个语句或函数
- defer后面可以使用语句调用,如果使用的是语句调用,那么传递的参数数据会被立即拷贝,而如果其后接的是一个匿名函数,那么在函数中直接使用的外部数据就是通过地址拷贝来进行处理的,也就是说外部调用过程中对该变量的任何操作都会反映在defer后的匿名函数中
- 当有多个defer行为被注册时,它们会以逆序的顺序执行,也就是先注册的后执行
- defer关键字主要作用是一些函数执行完之后进行的收尾工作
- 解锁一个加锁的资源
- 打印最终报告
- 关闭数据库链接
- 关于defer需要注意的一点是,其只会让其后的最外层函数或者最外层的语句在函数返回之前调用,而其外层函数或外层语句所需要的参数是会按照声明的顺序直接调用的,如:
// 这里首先调用tracing("a"),然后调用fmt.Println("in a"),最后再调用untracing()
defer untracing(tracing("a"))
fmt.Println("in a")
- 关于defer与声明式返回值,有一点需要说明的是,如果声明了返回值的名称,而return语句中又返回了另一个值,也就是说return语句返回的值与声明的返回值变量中的值不一致时,go在调用return语句时,会进行一步操作就是将return语句后的值赋值给声明的返回值变量中。那么这里存在的一个问题是,如果defer语句中修改了声明的返回值变量,那么无论return语句中返回的是什么,最终都是以defer语句中进行的修改为准,例如:
// 这里函数最终的返回值是2,因为return语句中首先将ret置为1,然后defer语句中将其自增为2了
func f() (ret int) {
defer func() {
ret++
}()
return 1
}
- 内置函数
名称 | 说明 |
---|---|
close | 用于管道通信 |
len和cap | len用于返回某个类型的长度或数量(字符串、数组、切片、map和管道);cap是容量的意思,用于返回某个类型的最大容量(只能用于切片和map) |
new和make | new和make均是用于分配内存:new用于值类型和用户定义的类型,如自定义结构,make用于内置引用类型(切片、map和管道)。它们的用法就像是函数,但是将类型作为参数:new(type)、make(type)。new(T)分配类型T的零值并返回其地址,也就是指向类型T的指针。它也可以用于基本类型:v := new(int)。make(T)返回类型T的初始化之后的值,因此它比new进行更多的工作,new()是一个函数,不要忘记它的括号 |
copy和append | 用于复制和连接切片 |
panic和recover | 两者均用于错误处理机制 |
print和println | 底层打印函数,在部署环境中建议使用fmt包 |
complex和real imag | 用于创建和操作复数 |
-
对于没有名称的函数,我们称为匿名函数,匿名函数是不能独立存在的,但是可以将其赋值给某个变量
-
匿名函数同样被称之为闭包:它们被允许调用定义在其他环境下的变量。闭包可使得某个函数捕捉到一些外部状态,例如:函数被创建时的状态,另一种表示方式为:一个闭包继承了函数所声明时的作用域。这种状态(作用域内的变量)都被共享到闭包的环境中,因此这些变量可以在闭包中被操作,直到被销毁。闭包经常被用作包装函数:它们预先定义好1个或多个参数以用于包装。另一个不错的闭包应用就是使用闭包来完成更加简洁的错误检查。
-
一个返回值为另一个函数的函数可以被称为工厂函数,这在我们需要创建一系列相似的函数的时候非常有用:书写一个工厂函数,而不是针对每种情况都书写一个函数。
-
可以返回其他函数的函数和接收其它函数作为参数的函数均被称之为高阶函数,是函数式语言的特点。