1、函数定义
函数是Go程序源代码的基本构造单位,一个函数的定义包括如下几个部分:函数声明关键字func、函数名、参数列表、返回列表和函数体。函数名遵循标识符的命名规则,首字母的大小写决定该函数在其他包的可见性:大写时其他包可见,小写时只有相同的包可以访问;函数的参数和返回值需要使用“()”包裹,如果只有一个返回值,而且使用的是非命名的参数,则返回参数的()”可以省略。函数体使用“}”包裹,并且“{”必须位于函数返回值同行的行尾。
func funcName(param-list)(result-list) {
function-body
}
函数的特点
- 函数可以没有输入参数,也可以没有返回值(默认返回0)。例如:
func A() {
//do something
}
func B() int {
//do shomething
return 1
}
- 多个相邻的相同类型的参数可以使用简写模式。例如:
func add(a, b int) int { // a int, b int 简写为a,b int
return a + b
}
- 支持有名的返回值,参数名就相当于函数体内最外层的局部变量,命名返回值变量会被初始化为类型零值,最后的return可以不带参数名直接返回。
//sum相当于函数内的局部变量,被初始化为零
func add(a, b int) (sum int) {
sum = a + b
return //return sum的简写模式
//sum := a + b //如果是sum := a + b,则相当于新声明一个sum变量命名返回变量sum覆盖
//return sum //最后要显示的调用return sum
}
- 不支持默认值参数
- 不支持函数重载
- 不支持函数嵌套,严格说是不支持命名函数的嵌套定义,但支持嵌套匿名函数。例如:
func add(a, b int) (sum int) {
anonymous := func(x, y int) int {
return x + y
}
return anonymous(a, b)
}
2、多值返回
Go函数支持多值返回,定义多值返回的返回参数列表时要使用"()"包裹,支持命名参数的返回。
func swap(a, b int) (int, int) {
return b, a
}
习惯用法:如果多值返回值有错误类型,则一般将错误类型作为最后一个返回值。
3、实参到形参的传递
Go函数实参到形参的传递永远是值拷贝,有时函数调用后实参指向的值发生了变化,那是因为参数传递的是指针值的拷贝,实参是一个指针变量,传递给形参的是这个指针变量的副本,二者指向同一地址,本质上参数传递仍然是值拷贝。例如:
package main
import "fmt"
func main() {
a := 10
chvalue(a) //实参传递给形参是值拷贝
fmt.Println(a)//10
chpointer(&a) //实参传递给形参仍然是值拷贝,只不过复制的是a的地址值
fmt.Println(a)//11
}
func chvalue(a int) int {
a = a + 1
return a
}
func chpointer(a *int) {
*a = *a + 1
return
}
4、不定参数
Go函数支持不定数目的形式参数,不定参数声明使用param …type的语法格式。
函数的不定参数有如下几个特点:
- 所有的不定参数类型必须是相同的。
- 不定参数必须是函数的最后一个参数
- 不定参数名在函数体内相当于切片,对切片的操作同样适合对不定参数的操作。例如:
func sum(arr ...int) (sum int) {//此时arr就相当于切片,可以使用range访问
for _, v := range arr {
sum += v
}
return
}
- 切片可以作为参数传递个不定参数,切片名后面要加上"…"。例如:
func suma(arr ...int) (sum int) {
for _, v := range arr {
sum += v
}
return
}
func main() {
slice := []int{1, 2, 3, 4}
array := [...]int{1, 2, 3, 4}
//数组不可以作为实参传递给不定参数的函数
suma(slice...)
}
- 形参为不定参数的函数和形参为切片的函数类型不相同。例如:
func sumb(arr ...int) (sum int) {
for _, v := range arr {
sum += v
}
return
}
func sumc(arr []int) (sum int) {
for v := range arr {
sum += v
}
return
}
//sumb和sumc的类型并不一样
fmt.Printf("%T\n", sumb)//func(...int) int
fmt.Printf("%T\n", sumc)//func([]int) int