1. 参数

1.1.1. 函数参数

函数定义时指出,函数定义时有参数,该变量可称为函数的形参。形参就像定义在函数体内的局部变量。

但当调用函数,传递过来的变量就是函数的实参,函数可以通过两种方式来传递参数:

值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

  1. func swap(x, y int) int {
  2. ... ...
  3. }

引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. /* 定义相互交换值的函数 */
  6. func swap(x, y *int) {
  7. var temp int
  8. temp = *x /* 保存 x 的值 */
  9. *x = *y /* 将 y 值赋给 x */
  10. *y = temp /* 将 temp 值赋给 y*/
  11. }
  12. func main() {
  13. var a, b int = 1, 2
  14. /*
  15. 调用 swap() 函数
  16. &a 指向 a 指针,a 变量的地址
  17. &b 指向 b 指针,b 变量的地址
  18. */
  19. swap(&a, &b)
  20. fmt.Println(a, b)
  21. }

输出结果:

  1. 2 1

在默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。

注意1:无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。

注意2:map、slice、chan、指针、interface默认以引用的方式传递。

不定参数传值 就是函数的参数不是固定的,后面的类型是固定的。(可变参数)

Golang 可变参数本质上就是 slice。只能有一个,且必须是最后一个。

在参数赋值时可以不用用一个一个的赋值,可以直接传递一个数组或者切片,特别注意的是在参数后加上“…”即可。

  1. func myfunc(args ...int) { //0个或多个参数
  2. }
  3. func add(a int, argsint) int { //1个或多个参数
  4. }
  5. func add(a int, b int, argsint) int { //2个或多个参数
  6. }

注意:其中args是一个slice,我们可以通过arg[index]依次访问所有参数,通过len(arg)来判断传递参数的个数.

任意类型的不定参数: 就是函数的参数和每个参数的类型都不是固定的。

用interface{}传递任意类型数据是Go语言的惯例用法,而且interface{}是类型安全的。

  1. func myfunc(args ...interface{}) {
  2. }

代码:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func test(s string, n ...int) string {
  6. var x int
  7. for _, i := range n {
  8. x += i
  9. }
  10. return fmt.Sprintf(s, x)
  11. }
  12. func main() {
  13. println(test("sum: %d", 1, 2, 3))
  14. }

输出结果:

  1. sum: 6

使用 slice 对象做变参时,必须展开。(slice…)

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func test(s string, n ...int) string {
  6. var x int
  7. for _, i := range n {
  8. x += i
  9. }
  10. return fmt.Sprintf(s, x)
  11. }
  12. func main() {
  13. s := []int{1, 2, 3}
  14. res := test("sum: %d", s...) // slice... 展开slice
  15. println(res)
  16. }