持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情
一、函数注意事项和细节讨论:
- 函数的形参列表可以是多个,返回值列表也可以是多个。
- 形参列表和返回值列表的数据类型可以是值类型和引用类型。
- 函数的命名遵循标识符命名规范,首字母不能是数字,首字母大写该函数可以被本包文件和其它包文件使用,类似public,首字母小写,只能被本包文件使用,其它包文件不能使用,类型 private
- 函数中的变量是局部的,函数外不生效。
package main
import "fmt"
func test() {
// n1 是 test 函数的局部变量,只能在test函数中使用
var n1 int = 10
}
func main() {
// 这里不能使用n1 ,因为 n1 是test 函数的局部变量
fmt.Println("n1="n1)
}
- 基本数据类型和数组默认都是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值。
值传递:拷贝了一份数据,不影响原来的数值,被拷贝的可以是值也可以是地址
引用传递:通过指针直接修改的源数值
package main
import "fmt"
func test02(n1 int) {
n1 = n1 + 10
fmt.Println("test01() n1=", n1)
}
func main() {
// 这里不能使用n1 ,因为 n1 是test 函数的局部变量
n1 := 20
test02(n1)
fmt.Println("main() n1=", n1)
}
main() 函数下 test02(n1) 进行了一个值拷贝 , 传递给 test02 函数
- 如果希望函数内的变量能修改函数外的变量(指的是默认以值传递的方式的数据类型),可以传入变量的地址 & ,函数内以指针的方式操作变量。从效果上看类似引用
值传递:传递的是原本的数值
引用传递:传递地址值
*:取值
&:取地址
package main
import "fmt"
// n1 就是 *int 类型
func test03(n1 *int) {
*n1 = *n1 + 10
fmt.Println("test03() n1=", *n1)
}
func main() {
num := 20
test03(&num)
fmt.Println("main() num=", num)
}
- Go 函数不支持重载
- 在 GO 中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用。
package main
import "fmt"
// 在 GO 中,函数也是一种数据类型,
// 可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用。
func getSum(n1 int, n2 int) int {
return n1 + n2
}
func main() {
a := getSum
fmt.Printf("a的类型%T\ngetSum类型是%T\n", a, getSum)
res := a(10, 40) // 等价于 res := getSum(10,40)
fmt.Println("res=", res)
}
- 函数既然是一种数据类型,因此在GO中,函数可以作为形参,并且调用!
package main
import "fmt"
// 在 GO 中,函数也是一种数据类型,
// 可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用。
func getSum(n1 int, n2 int) int {
return n1 + n2
}
// 函数既然是一种数据类型,因此在GO中,函数可以作为形参,并且调用!
func myFun(funvar func(int, int) int, num1 int, num2 int) int {
return funvar(num1, num2)
}
func main() {
a := getSum
fmt.Printf("a的类型%T\ngetSum类型是%T\n", a, getSum)
res := a(10, 40) // 等价于 res := getSum(10,40)
fmt.Println("res=", res)
// 看案例:
res2 := myFun(getSum, 50, 60)
fmt.Println("res2=", res2)
}
- 为了简化数据类型定义,GO支持自定义数据类型
-
- 基本语法:
type 自定义数据类型名 数据类型 // 理解:相当于一个别名 - 案例:
type mylnt int // 这时 myint 就等于 int 来使用了 - 案例:
type mySum func (int ,int)int //这时 mySum 就等价于一个函数类型 func (int,int) int
- 基本语法:
package main
import "fmt"
// 在 GO 中,函数也是一种数据类型,
// 可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用。
func getSum(n1 int, n2 int) int {
return n1 + n2
}
// 函数既然是一种数据类型,因此在GO中,函数可以作为形参,并且调用!
// func myFun(funvar func(int, int) int, num1 int, num2 int) int {
// return funvar(num1, num2)
// }
// 再举一个案例:
// 案例 二
// 这时 myFunType 就是 func(int,int)int
type myFunType func(int, int) int // 这时 myFunType
func myFun2(funvar myFunType, num1 int, num2 int) int {
return funvar(num1, num2)
}
func main() {
// 案例 一:
// 给 int 取了别名,在go中 myInt 和 int ,虽然都是数据类型,但是go认为 myInt 和 int 是两个类型
type myInt int
var num1 myInt
var num2 int
num1 = 40
num2 = int(num1) // 各位,注意这样依然需要显示转换,go 认为myInt和int两个类型
fmt.Println("num1=", num1, "num2", num2)
res3 := myFun2(getSum, 50, 60)
fmt.Println("res3=", res3)
}
- 支持对函数返回值的命名
package main
import "fmt"
// 支持对函数返回值命名:
func getSumAndSub(n1 int, n2 int) (sum int, sub int) {
sum = n1 + n2
sub = n1 - n2
return
}
func main() {
// 看案例:
a, b := getSumAndSub(1, 2)
fmt.Printf("a=%v b=%v\n", a, b)
}