golang学习笔记9:函数参数与返回值

按值传递和按引用传递 Go 默认使用按值传递来传递参数,也就是传递参数的副本。函数接收参数副本之后,在使用变量的过程中可能对副本的值进行更改,但不会影响到原来的变量,比如 Function...

按值传递和按引用传递

Go 默认使用按值传递来传递参数,也就是传递参数的副本。函数接收参数副本之后,在使用变量的过程中可能对副本的值进行更改,但不会影响到原来的变量,比如 Function(arg1)。

如果你希望函数可以直接修改参数的值,而不是对参数的副本进行操作,你需要将参数的地址(变量名前面添加&符号,比如 &variable)传递给函数,这就是按引用传递,比如 Function(&arg1),此时传递给函数的是一个指针。如果传递给函数的是一个指针,指针的值(一个地址)会被复制,但指针的值所指向的地址上的值不会被复制;我们可以通过这个指针的值来修改这个值所指向的地址上的值。(译者注:指针也是变量类型,有自己的地址和值,通常指针的值指向一个变量的地址。所以,按引用传递也是按值传递。)

几乎在任何情况下,传递指针(一个32位或者64位的值)的消耗都比传递副本来得少。

在函数调用时,像切片(slice)、字典(map)、接口(interface)、通道(channel)这样的引用类型都是默认使用引用传递(即使没有显式的指出指针)。

传递变长参数

如果函数的最后一个参数是采用 ...type 的形式,那么这个函数就可以处理一个变长的参数,这个长度可以为 0,这样的函数称为变参函数。

func myFunc(a, b, arg ...int) {}

这个函数接受一个类似某个类型的 slice 的参数 ,该参数可以通过for 循环结构迭代。

示例函数和调用:

func Greeting(prefix string, who ...string)
Greeting("hello:", "Joe", "Anna", "Eileen")

在 Greeting 函数中,变量 who 的值为 []string{"Joe", "Anna", "Eileen"}。

如果参数被存储在一个数组 arr 中,则可以通过 arr... 的形式来传递参数调用变参函数。

defer 和追踪

关键字 defer 允许我们推迟到函数返回之后(或任意位置执行 return 语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为 return 语句同样可以包含一些操作,而不是单纯地返回某个值)。关键字 defer 的用法类似于面向对象编程语言 Java 和 C# 的 finally 语句块,它一般用于释放某些已分配的资源。

package main

import"fmt"

func main(){

function1()

}

func function1(){

fmt.Printf("In function1 at the top\n")

defer function2()

fmt.Printf("In function1 at the bottom!\n")

}

func function2(){

fmt.Printf("function2: Deferred until the end of the calling function!")

}

输出:

In Function1 at the topIn Function1 at the bottom!
Function2: Deferred until the end of the calling function!

当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出):

func f(){

for i :=0; i <5; i {

defer fmt.Printf("%d ", i)

} }

上面的代码将会输出:4 3 2 1 0。

将函数作为参数

package main

import("fmt")

func main()

{    callback(1, Add)   }

func Add(a, b int){

fmt.Printf("The sum of %d and %d is: %d\n", a, b, a b)}

func callback(yint, f func(int,int)){

f(y,2)// this becomes Add(1, 2)

}

闭包

当我们不希望给函数起名字的时候,可以使用匿名函数,例如:func(x, y int) int { return x y }。

这样的一个函数不能够独立存在(编译器会返回错误:non-declaration statement outside function body),但可以被赋值于某个变量,即保存函数的地址到变量中:fplus := func(x, y int) int { return x y },然后通过变量名对函数进行调用:fplus(3,4)。

当然,也可以直接对匿名函数进行调用:func(x, y int) int { return x y } (3, 4)。

  • 发表于 2018-10-22 10:13
  • 阅读 ( 413 )
  • 分类:默认分类

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
不写代码的码农
Kemin

架构工程师

45 篇文章

作家榜 »

  1. Kemin 45 文章
  2. golanglover 5 文章
  3. D.Chen 4 文章
  4. salamander 1 文章
  5. 深圳-伟 1 文章
  6. 广训 1 文章
  7. PHP小菜 1 文章
  8. Undefined 0 文章