一、函数基本使用
一)函数概述
1、函数定义
对特定的功能进行提取,形成一个代码片段
2、函数的作用
提高代码的复用性,减少代码的冗余,代码的维护性也提高了
3、函数中间的关系
函数与函数是并列关系,所以定义的函数不能放到main函数中
4、基本语法
func 函数名 (形参列表) (返回值类型列表) {执行语句return + 返回值列表 }
函数名
- 遵循标识符命名规范:见明知意 addNum
- 首字母不能是数字
- 首字母大些 该函数可以被本包文件和其他包文件使用(类似public)
- 首字母小写只能被本包文件使用,其他包文件不能使用(类似private)
形参列表
- 形参列表:可以一个参数,也可以是n个参数,可以是0个参数
- 形式参数参数:作用,接收外来的数据
- 实际参数:实际传入的数据
func calc(num1 int, num2 int) int {var sum int = 0sum += num1sum += num2return sum }func main() {sum := calc(10, 20)fmt.Println(sum) }
返回值类型列表
返回值类型列表:返回的返回值对应的类型应该写在这个列表中
- 返回0个:若没有返回值,那么返回值类型什么都不写就可以
func calc(num1 int, num2 int) { //若返回值类型就一个的话,那么()是可以省略不写的var sum int = 0sum += num1sum += num2//return sumfmt.Println(sum)
}func main() {//功能//调用函数calc(10, 20)//fmt.Println(sum)
}
- 返回1个:若返回值类型就一个的话,那么()是可以省略不写的
func calc(num1 int, num2 int) int { //若返回值类型就一个的话,那么()是可以省略不写的var sum int = 0sum += num1sum += num2return sum//fmt.Println(sum)
}func main() {//功能//调用函数//calc(10, 20)sum := calc(10,20)fmt.Println(sum)
}
- 返回多个
func calc2(num1 int, num2 int) (int, int) { //若返回值类型就一个的话,那么()是可以省略不写的var sum int = 0sum += num1sum += num2var result int = num1 - num2return sum, result//fmt.Println(sum)
}func main() {//功能//调用函数//calc(10, 20)//sum := calc(10, 20)//fmt.Println(sum)sum1, result1 := calc2(30, 20)fmt.Println("sum1 is ", sum1)fmt.Println("result1 is ", result1)
}
若有返回值不想接受,那么可以利用_进行忽略
二)函数实战
1、函数实现:两个数交换(内存分析)
错误示例:下面的方式不能实现数字交换,执行交换函数前后结果相同
单纯的值传递对函数外面的值没有影响
//自定义函数:交换两个数 func exchangeNum(num1 int, num2 int) {var t intt = num1num1 = num2num2 = t }func main() {//调用函数var num1 int = 10var num2 int = 20fmt.Printf("The two numbers before exchange: num1 = %v,num2 = %v\n", num1, num2)exchangeNum(num1, num2)fmt.Printf("The two numbers after exchange: num1 = %v,num2 = %v\n", num1, num2) }
正确做法:通过使用指针来进行数据的交换
//自定义函数:交换两个数 func exchangeNum(num1 *int, num2 *int) {t := *num1*num1 = *num2*num2 = t }func main() {//调用函数num1 := 10num2 := 20fmt.Printf("The two numbers before exchange: num1 = %v,num2 = %v\n", num1, num2)exchangeNum(&num1, &num2)fmt.Printf("The two numbers after exchange: num1 = %v,num2 = %v\n", num1, num2) }
输出结果如下
The two numbers before exchange: num1 = 10,num2 = 20 The two numbers after exchange: num1 = 20,num2 = 10
2、golang函数不支持重载
函数重载:不支持同时定义两个名字一样的函数
3、支持可变参数(若希望函数带有可变数量的参数)
//定义一个函数,函数的参数为可变参数,参数的数量可变 //args...int 可以传入任意多(0-n)个数量的int类型的数据 func test(args ...int) {//函数内部处理可变参数时,将可变参数当做切片来处理//遍历可变函数:for i := 0; i < len(args); i++ {fmt.Println(args[i])} }func main() {test()fmt.Println("-------------------------------------------")test(8)fmt.Println("-------------------------------------------")test(1, 16, 168, 1688) }
输出结果
------------------------------------------- 8 ------------------------------------------- 1 16 168 1688
4、基本数据类型和数组默认都是值传递的,即进行拷贝。在函数内修改,不会影响到原来的值
5、以值传递方式的数据类型,若希望在函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量
6、函数也是一种数据类型,可以赋值给一个变量,则此变量就成为一个函数类型的变量了。通过改变量可以对函数调用。
package mainimport "fmt"//定义一个函数 func test(num int) {fmt.Println(num) }func main() {//函数也是一种数据类型,可以赋值给一个变量a := test //变量就是一个函数类型的变量fmt.Printf("a的类型是: %T, test函数的类型是: %T \n", a, test)//a的类型是:func(int),test的函数类型是func(int)//通过该变量可以对函数调用a(10) }
7、函数既然是一种数据类型,因此函数可以作为形参,并且可以调用
package mainimport "fmt"//定义一个函数 func test(num int) {fmt.Println(num) }func test02(num1 int, num2 float32, testFunc func(int)) {fmt.Println("-----test02") } func main() {//函数也是一种数据类型,可以赋值给一个变量a := test //变量就是一个函数类型的变量fmt.Printf("a的类型是: %T, test函数的类型是: %T \n", a, test)//a的类型是:func(int),test的函数类型是func(int)//通过该变量可以对函数调用a(10) //等价于 test(10)//调用test02函数test02(10, 3.19, test)test02(10, 3.19, a) }
8、为了简化数据类型定义,go支持自定义数据类型
基本语法:type 自定义数据类型名 数据类型
自定义数据类型相当于起个别名
实战1
type myInt int ————>myInt就等价于int
func main() {//自定义数据类型:(相当于起别名)给int类型起了个别名叫myInt类型type myInt intvar num1 myInt = 30fmt.Println("num1", num1)var num2 int = 30//num2 = num1 //虽然是别名,但是在go中编译识别时,还是认为myInt和int不是一种数据类型num2 = int(num1)fmt.Println("num2", num2) }
实战2
type mySum func(int, int) int ————>此时mySum就等价一个函数类型func(int, int) int
type myFunc func(int) func test03(num1 int, num2 float32, testFunc myFunc) {fmt.Println("-----test03") }
9、支持函数返回值命名
传统写法要求:返回值和返回值的类型对应,顺序不能差
func test04(num1 int, num2 int) (int, int) {result01 := num1 + num2result02 := num1 - num2return result01, result02 }
升级写法:对函数返回值命名,里面顺序就无所谓了,顺序不用对应
//定义一个函数:求两个数的和、差 func test05(num1 int, num2 int) (sum int, sub int) {result02 := num1 - num2result01 := num1 + num2fmt.Println(result01, result02)return result02, result01 }