简介
函数是基本的代码块,用于执行一个任务。
Go 语言最少有个 main() 函数,你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务,函数声明告诉了编译器函数的名称,返回类型,和参数。
Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。
初识函数
func function_name( [parameter list] ) [return_types] {
函数体
[return 返回值列表]
}
参数
位置参数
顾名思义,按照形参位置对应填写实参即可。
函数定义
func plus(n1 int){
fmt.Println(n1+1)
}
使用
n1 := 10
plus(n1)
默认值/可选参数
没有~,可基于函数闭包实现,等函数式编程一节再讲。
关键字参数
没有~,可基于map实现
可变参数
function_name(args... type)
注意:可变参数放到位置参数后面
函数定义
func sum(nums... int) {
fmt.Printf("形参nums的类型为:%T\n",nums)
all := 0
for _,num := range nums{
all += num
}
fmt.Println(all)
}
注意:可变参数,形参的类型为切片,可看后面截图。
使用
sum(3,4,5)
sum(1,2,3,4,5)
参数传递
值传递
数字、字符串、布尔、数组、结构体struct
引用传递(地址拷贝)
指针、切片slice、map、管道、interface
其实都是值传递,关键在于拷贝了值还是地址
函数定义
func mix(num int,flag bool, str string, arr [3]int, p Person,slice []int,kwarg map[string]string) {
num++
fmt.Println("mix() num:",num)
flag = false
fmt.Println("mix() flag:",flag)
str = "wanna change"
fmt.Println("mix() str:",str)
arr[0] = 99
fmt.Println("mix() arr:",arr)
p.Name = "Frank"
fmt.Println("mix() p:",p)
slice[0] = 99
fmt.Println("mix() slice:",slice)
kwarg["lady"] = "killer"
fmt.Println("mix() kwarg",kwarg)
}
使用
num := 3
flag := true
str := "lady_killer9"
arr := [3]int{}
p := Person{Name:"frankyu"}
slice:=[]int{1,2,3}
kwarg := map[string]string{"lady":"9"}
mix(num,flag,str,arr,p,slice,kwarg)
fmt.Println("main() num:",num)
fmt.Println("main() flag:",flag)
fmt.Println("main() str:",str)
fmt.Println("main() arr:",arr)
fmt.Println("main() p:",p)
fmt.Println("main() slice:",slice)
fmt.Println("main() kwarg:",kwarg)
返回值
多个返回值
函数定义
func get_sum(n1,n2 int) (int,int) {
return n1+n2, n1-n2
}
使用
fmt.Println(get_sum(n1,10))
返回值命名
函数定义
func get_plus(n1,n2 int) (sum int, differ int){
sum = n1+n2
differ = n1-n2
return
}
使用
fmt.Println(get_plus(a,b))
注意项
- 首字母大写就可以被其他包使用,类似C++的Public
- 基本数据类型和数组是值传递,函数内修改不会对函数外的变量产生影响
- 需要通过函数修改外部变量时,可以传递地址,用指针做形参
- 函数不支持传统的函数重载
- 函数也是一个数据类型,可以将函数赋给其他变量
- 支持对函数返回值命名
init函数
每个go文件中,都可以有一个init函数,做一些初始化的工作,在main函数运行前,go框架会调用init函数
go文件扫描顺序:全局变量定义->init函数->main函数
代码
func init() {
fmt.Println("我是init,在main函数前执行...")
}
匿名函数
没有名字的函数,只使用一次
代码
res := func (n int,m int) int{
return n+m
}(10,20)
defer
在函数中,程序员经常需要创建资源(比如:数据库连接、文件句柄、锁等),为了在函数执行完毕后,及时的释放资源,Go的设计者提供defer(延时机制)。
defer有个栈,先入后出,入栈时连同变量
代码
func deferUse() {
defer fmt.Println("defer begin...but display last")
defer fmt.Println("defer end...but display first")
}
全部代码
package main
import "fmt"
//-------位置参数---------
func plus(n1 int){
fmt.Println(n1+1)
}
//-------可变参数---------
func sum(nums... int) {
fmt.Printf("形参nums的类型为:%T\n",nums)
all := 0
for _,num := range nums{
all += num
}
fmt.Println(all)
}
type Person struct {
Name string
}
//-------传递方式--------
func mix(num int,flag bool, str string, arr [3]int, p Person,slice []int,kwarg map[string]string) {
num++
fmt.Println("mix() num:",num)
flag = false
fmt.Println("mix() flag:",flag)
str = "wanna change"
fmt.Println("mix() str:",str)
arr[0] = 99
fmt.Println("mix() arr:",arr)
p.Name = "Frank"
fmt.Println("mix() p:",p)
slice[0] = 99
fmt.Println("mix() slice:",slice)
kwarg["lady"] = "killer"
fmt.Println("mix() kwarg",kwarg)
}
//------指针----------
func swap(a,b *int){
*a,*b = *b,*a
}
//-------返回值----------
func get_sum(n1,n2 int) (int,int) {
return n1+n2, n1-n2
}
//------返回值命名-------
func get_plus(n1,n2 int) (sum int, differ int){
sum = n1+n2
differ = n1-n2
return
}
//--------defer-----------
func deferUse() {
defer fmt.Println("defer begin...but display last")
defer fmt.Println("defer end...but display first")
}
func init() {
fmt.Println("我是init,在main函数前执行...")
}
func main() {
fmt.Println("我是main,我要执行啦...")
//------------位置参数-----------
n1 := 10
plus(n1)
//------------可变参数------------
sum(3,4,5)
sum(1,2,3,4,5)
//-----------参数传递------------
num := 3
flag := true
str := "lady_killer9"
arr := [3]int{}
p := Person{Name:"frankyu"}
slice:=[]int{1,2,3}
kwarg := map[string]string{"lady":"9"}
mix(num,flag,str,arr,p,slice,kwarg)
fmt.Println("main() num:",num)