函数

  • Post author:
  • Post category:其他



函数声明


函数构成代码执行的逻辑结构。在

Go

语言中,函数的基本组成为:关键字

func

、函数名、

参数列表、返回值、函数体和返回语句。






package mymath
import "errors"
func Add(a int, b int) (ret int, err error) {
if a < 0 || b < 0 { // 假设这个函数只支持两个非负数字的加法
err= errors.New("Should be non-negative numbers!")
return
}
return a + b, nil // 支持多重返回值
}

函数调用

先导包,包必须在gopath/src中


Go

语言中函数名字的大小写不仅仅是风格,更直接体现了该函数的可见性,这一点尤其需

要注意。




小写字母开头的函数只在本包内可见,大写字母开头的函数才

能被其他包使用。

这个规则也适用于类型和变量的可见性。


不定参数



1不定参数类型


不定参数是指函数传入的参数个数为不定数量。为了做到这点,首先需要将函数定义为接受

不定参数类型:


func

myfunc(args …

int

) {



for

_, arg :=

range

args {


fmt.Println(arg)

}

}






















形如

…type

格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数。


























如果你希望传任意类型,可以指定类型为


interface{}














package main
import "fmt"
func MyPrintf(args ...interface{}) {
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg, "is an int value.")
case string:
fmt.Println(arg, "is a string value.")
case int64:
fmt.Println(arg, "is an int64 value.")
default:
fmt.Println(arg, "is an unknown type.")
}
}
}
func main() {
var v1 int = 1
var v2 int64 = 234
var v3 string = "hello"
var v4 float32 = 1.234
MyPrintf(v1, v2, v3, v4)
}
该程序的输出结果为:
1 is an int value.
234 is an int64 value.
hello is a string value.
1.234 is an unknown type.

多返回值


比如

File.Read()



数就可以同时返回读取的字节数和错误信息。如果读取文件成功,则返回值中的

n

为读取的字节

数,

err



nil

,否则

err

为具体的出错信息:


func

(file *File) Read(b []

byte

) (n

int

, err Error)


同样,从上面的方法原型可以看到,我们还可以给返回值命名,就像函数的输入参数一样。

返回值被命名之后,它们的值在函数开始的时候被自动初始化为空。在函数中执行不带任何参数



return

语句时,会返回对应的返回值变量的值。






















匿名函数与闭包







Go

里面,函数可以像普通变量一样被传递或使用,这与

C

语言的回调函数比较类似。不同

的是,

Go

语言支持随时在代码里定义匿名函数。

匿名函数由一个不带函数名的函数声明和函数体组成,如下所示:


func

(a, b

int

, z

float64

)

bool

{



return

a*b <

int

(z)

}


匿名函数可以直接赋值给一个变量或者直接执行

:























闭包


Go

的匿名函数是一个闭包,下面我们先来了解一下闭包的概念、价值和应用场景。





基本概念


闭包是可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块内或者

任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含

在代码块中,所以这些自由变量以及它们引用的对象没有被释放)为自由变量提供绑定的计算环

境(作用域)。






包的价




闭包的价值在于可以作为函数对象或者匿名函数,对于类型系统而言,这意味着不仅要表示

数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这些函数可以存储到

变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。




Go

语言中的闭包


Go

语言中的闭包同样也会引用到函数外的变量。闭包的实现确保只要闭包还被使用,那么

被闭包引用的变量会一直存在













package main
import (
"fmt"
)
func main() {
var j int = 5
a := func()(func()) {
var i int = 10
return func() {
fmt.Printf("i, j: %d, %d\n", i, j)
}
}()
a()
j *= 2
a()
}

错误处理














Go

语言引入了一个关于错误处理的标准模式,即

error

接口,该接口的定义如下:


type

error

interface

{


Error()

string


}


































defer
























延迟到return之前执行
























另外,一个函数中可以存在多个

defer

语句,因此需要注意的是,

defer

语句的调用是遵照

先进后出的原则,即最后一个

defer

语句将最先被执行。




















panic()



recover()








在一个函数执行过程中调用

panic()

函数时,正常的函数执行流程将立即终止,但函数中

之前使用

defer

关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致

逐层向上执行

panic

流程,直至所属的

goroutine

中所有正在执行的函数被终止。错误信息将被报

告,包括在调用

panic()

函数时传入的参数,这个过程称为错误处理流程。













recover()

函数用于终止错误处理流程。一般情况下,

recover()

应该在一个使用

defer


关键字的函数中执行以有效截取错误处理流程。如果没有在发生异常的

goroutine

中明确调用恢复

过程(使用

recover

关键字),会导致该

goroutine

所属的进程打印异常信息后直接退出























转载于:https://www.cnblogs.com/tomhuang/p/11535879.html