GO语言基础入门--函数
函数
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 // 支持多重返回值 }
如果参数列表中若干个相邻的参数类型相同,可以省略前面变量的类型声明,如:
func Add(a, b int</span>)(ret int, err error) { // ... }如果返回值列表中多个返回值的类型相同,也可以用同样的方式合并。
如果函数只有一个返回值,也可以这么写:
func Add(a, b int) int { // ... }
函数调用
import "mymath"// 假设Add被放在一个叫 mymath的包中 // ... c := mymath.Add(1, 2)
值得注意的是:如果想在外部调用该包函数,所调用的函数名必须大写。
这个规则也适用于类型和变量的可见性。
不定参数
func myfunc(args ... int) {//参数名 ...type for _, arg := range args { fmt.Println(arg) } }该函数可接收不定数量参数,如:
myfunc(2, 3, 4) myfunc(1, 3, 7, 13)
从内部实现机理上来说,类型...type本质上是一个数组切片,也就是[]type,这也是为什么上面的参数args可以用for循环来获得每个传入的参数。
假如没有...type这样的语法糖,开发者将不得不这么写:
func myfunc2(args [] int) { for _, arg := range args { fmt.Println(arg) } }从函数的实现角度来看,这没有任何影响,该怎么写就怎么写。但从调用方来说,情形则完全不同:
myfunc2([] int{1, 3, 7, 13})你会发现,我们不得不加上[]int{} 来构造一个数组切片实例。
func myfunc(args ... int) { // 按原样传递 myfunc3(args...) // 传递片段,实际上任意的int slice都可以传进去 myfunc3(args[1:]...) }
func Printf(format string, args ... 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.
匿名函数和闭包
的是, Go语言支持随时在代码里定义匿名函数。
匿名函数由一个不带函数名的函数声明和函数体组成,如下所示:
func(a, b int, z float64) bool { return a*b <int(z) }
匿名函数可以直接赋值给一个变量或者直接执行:
f := func(x, y int) int { return x + y } func(ch chan int) { ch <- ACK } (reply_chan) // 花括号后直接跟参数列表表示函数调用
闭包
任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含
在代码块中,所以这些自由变量以及它们引用的对象没有被释放)为自由变量提供绑定的计算环
境(作用域)。
被闭包引用的变量会一直存在, 如:
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() }
上述例子的执行结果是:
i, j: 10, 5 i, j: 10, 10
在上面的例子中,变量a指向的闭包函数引用了局部变量i和j , i的值被隔离,在闭包外不
能被修改,改变j 的值以后,再次调用a,发现结果是修改过的值。
在变量a指向的闭包函数中,只有内部的匿名函数才能访问变量i,而无法通过其他途径访问
到,因此保证了i的安全性。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。