一、函数基本使用
一)函数概述
1、函数定义
对特定的功能进行提取,形成一个代码片段
2、函数的作用
提高代码的复用性,减少代码的冗余,代码的维护性也提高了
3、函数中间的关系
函数与函数是并列关系,所以定义的函数不能放到main函数中
4、基本语法
func 函数名 (形参列表) (返回值类型列表) { 执行语句 return + 返回值列表 }
函数名
- 遵循标识符命名规范:见明知意 addNum
- 首字母不能是数字
- 首字母大些 该函数可以被本包文件和其他包文件使用(类似public)
- 首字母小写只能被本包文件使用,其他包文件不能使用(类似private)
形参列表
- 形参列表:可以一个参数,也可以是n个参数,可以是0个参数
- 形式参数参数:作用,接收外来的数据
- 实际参数:实际传入的数据
func calc(num1 int, num2 int) int { var sum int = 0 sum += num1 sum += num2 return sum } func main() { sum := calc(10, 20) fmt.Println(sum) }
返回值类型列表
返回值类型列表:返回的返回值对应的类型应该写在这个列表中
- 返回0个:若没有返回值,那么返回值类型什么都不写就可以
func calc(num1 int, num2 int) { //若返回值类型就一个的话,那么()是可以省略不写的
var sum int = 0
sum += num1
sum += num2
//return sum
fmt.Println(sum)
}
func main() {
//功能
//调用函数
calc(10, 20)
//fmt.Println(sum)
}
- 返回1个:若返回值类型就一个的话,那么()是可以省略不写的
func calc(num1 int, num2 int) int { //若返回值类型就一个的话,那么()是可以省略不写的
var sum int = 0
sum += num1
sum += num2
return 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 = 0
sum += num1
sum += num2
var result int = num1 - num2
return 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 int t = num1 num1 = num2 num2 = t } func main() { //调用函数 var num1 int = 10 var num2 int = 20 fmt.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 := 10 num2 := 20 fmt.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 main import "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 main import "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 int var num1 myInt = 30 fmt.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 + num2 result02 := num1 - num2 return result01, result02 }
升级写法:对函数返回值命名,里面顺序就无所谓了,顺序不用对应
//定义一个函数:求两个数的和、差 func test05(num1 int, num2 int) (sum int, sub int) { result02 := num1 - num2 result01 := num1 + num2 fmt.Println(result01, result02) return result02, result01 }