# 函数/Function

# 函数声明

Go 的函数声明分为五部分:

  1. 关键字 func
  2. 函数名,大写开头表示可以导出,小写则不行。
  3. 参数列表
  4. 返回值列表
  5. 函数体
func fn(x int) int {
  // ...
}

# 参数拷贝

Go 语言中,函数参数传递采用是 值传递 的方式。 所谓“值传递” , 就是将实际参数在内存 中的表示 逐位拷贝 ( Bitwise Copy ) 到形式参数中。 对于像整型、 数组、 结构体这类类 型,它们的内存表示就是它们自身的数据内容,因此当这些类型作为实参类型时,值传递 拷贝的就是它们自身,传递的开销也与它们自身的大小成正比。

但是像 string、 切片、 map 这些类型就不是了,它们的内存表示对应的是它们数据内容 的 “描述符” 。 当这些类型作为实参类型时,值传递拷贝的也是它们数据内容的“描述 符” , 不包括数据内容本身,所以这些类型传递的开销是固定的,与数据内容大小无关。 这种只拷贝“描述符” , 不拷贝实际数据内容的拷贝过程,也被称为 “浅拷贝” 。

# 变长入参

假如声明函数时,我们还不确定会有多少个参数,就可以使用变长入参。通过 ... 实现。

// 声明参数elems为可变长入参
func myFnc(elems ...int){
  fmt.Println(elems...)
}

func main(){
  // 3个参数
  myFnc(1,2,3)
  // 2个参数
  myFnc(4,5)
}

输出结果

[1,2,3]
[4,5]

在 Go 中, 变长参数实际上是通过切片来实现的 。 所以,我们在函数体中, 就可以使用切片支持的所有操作来操作变长参数,这会大大简化了变长参数的使用复杂度。

# 支持多返回值

Go 函数支持多返回值:

func foo()                        //无返回值
func foo() error                  //仅有一个返回值
func foo()(int,string,error)      //有2或2个以上返回值

如果是 2 个或 2 个以上的返回值,我们需要用括号括起来