函数
//基本语法
func 函数名 (形参列表) (返回值列表) {
函数体
}
- 函数的命名规则遵循标识符命名规范,首字母大写的函数可以被本包文件和其他文件使用,类似与public;首字母小写的文件只能被本包使用,类似于private(相当于python面向对象中的单双下划线函数);
- go函数不支持重载。
- golang里函数也是一种数据类型,可以赋值给变量,该变量可以对函数调用
func getSum(n1 int ,n2 int) int {
return n1 + n2
}
func main() {
a := getSum
fmt.Printf("a的类型是%T,getSum的类型是%T\n",a,getSum)
res := a(10,20) // 等价于a := getSum(10,20)
fmt.Println(res)
}
//a的类型是func(int, int) int getSum的类型是func(int, int) int
//30
- go函数可以作为形参被调用
func getSum(n1 int ,n2 int) int {
return n1 + n2
}
func mydef(def func(int,int) int,num1 int ,num2 int) int {
return def(num1,num2)
}
func main() {
res2 := mydef(getSum,10,20)
fmt.Println(res2)
}
- 支持函数返回值命名
func cal(n1 int) (n2 int) {
n2 = n1 + 1
return
}
- 自定义数据类型
func main() {
type myInt int // 给int取的别名
var num1 myInt = 40
var num2 int
num2 = int(num1) // 虽然都是int类型,但是还是需要转换
fmt.Printf("%T,%d",num1,num2)
type mydefType func(int,int) int //mydefType就等于func(int,int) int类型
}
- 支持可变参数args(相当于python中的*args,**kwargs:*表示’tuple’类型,**表示’dict’类型)
func sum(n1 int,args... int) int {
sum := n1
//遍历args 名字无所谓,啥都行(符合命名规范)
for i:= 0;i<len(args);i++ {
sum += args[i] // args是切片类型
}
return sum
}
func main() {
fmt.Println(sum(1,1,2,3,45,65))
}
//117
return语句
return有几个小细节,go函数可以返回多个值(python也可,但C/java不行),但是go在返回多个值时,如果在接收时想忽略某个值,可以使用_去忽略;返回值只有一个时,可以不写()。
func cal(n1 int ,n2 int) (sum int,sub int) {
sum = n1 + n2
sub = n1 - n2
return
}
func main() {
res,_ :=cal(20,10)
fmt.Println(res)
}
init函数
类似java中的构造方法,python中的实例化对象。init函数在main函数之前被调用
var Age int
var Name string
func init() {
Age = 18
Name = "flandre"
}
如果一个go文件同时包含全局变量、init函数和main函数。执行流程为全局变量定义==>init函数==>main函数。
匿名函数
就是python中的lambda。
func main() {
// 定义匿名函数时直接调用
res := func(n1 int,n2 int) int {
return n1+n2
}(10,20)
fmt.Println(res)
// 将匿名函数直接赋给变量,然后调用a
lambda := func(n1 int,n2 int) int {
return n1+n2
}
res2 := lambda(10,20)
fmt.Println(res2)
}
//30
//30
全局匿名函数在整个全局有效
var (
Fun1 = func(n1 int,n2 int) int {
return n1*n2
)
闭包
函数套函数(python是这样的)
func AddUpper() func(int) int {
var n int = 10
return func(x int) int {
n = n + x
return n
}
}
func main() {
f := AddUpper()
fmt.Println(f(1)) // 11
fmt.Println(f(2)) // 13
}
defer
一种延时机制,执行到defer时,会将代码语句压栈,函数执行完毕再执行,所以会先输出最下面的defer代码
func main() {
//defer关键字 压栈形式,先输出end2
defer fmt.Println("main end1")
defer fmt.Println("main end2")
fmt.Println("main::hello go 1")
fmt.Println("main::hello go 2")
}
//main::hello go 1
//main::hello go 2
//main end2
//main end1
defer将语句放入栈中时,也会将相关的值拷贝同时放入栈
func sum(n1 int ,n2 int) int {
defer fmt.Println("n1 = ",n1) // n1 = 10
defer fmt.Println("n2 = ",n2) // n2 = 20
res := n1 + n2 // res = 30
n1++ // n1 =11
fmt.Println("res = ",res ,"n1 = ",n1) // res=30 n1=11
return res
}
func main() {
sum(10,20)
}
//res = 30 n1 = 11
//n2 = 20
//n1 = 10
defer主要用于释放函数创建的资源,模拟代码如下:
func test() {
//释放文件资源
file = openfile(文件名)
defer file.close()
//释放数据库资源
connect = openDatabase()
defer connect.close()
}
参数传递
- 值传递:数据越大,效率越低。
- 引用传递:地址的拷贝,数据量小。
func test_print(num *int) {
print(*num)
}
func main() {
num := 20
test_print(&num)
}