Go语言学习笔记(五) [函数]

日期:2014年7月29日

一、函数定义

函数定义: func (p type) funcname (q int) (r,s int) {return 0,0 }

func:保留字,用于定义一个函数

(p type):可选的,用于定义特定的函数类型,俗称方法。

funcname:函数名

(q int) :q作为输入参数,在Go中函数参数是按传值方式传递的。

(r,s int):变量r,s是这个函数的命名返回值,在Go中函数可以返回多个值,如果不想对返回的参数命名,只需要提供类型:(int,int)。如果只有一个返回值,可以省

略圆括号。如果函数是一个子过程,并且没有任何返回值,也可以省略这些内容

{return 0,0 }:函数体。

说明:函数的定义顺序可以随意安排,编译器会在执行前扫描每个文件。Go 不允许函数嵌套。然而你可以利用匿名函数实现它。

二、函数递归

函数递归的例子

func rec(i int) {

if i == 10 {

return

}

rec(i+1)

fmt.Printf("%d ",i)

}

三、作用域

在 Go 中,定义在函数外的变量是全局的,那些定义在函数内部的变量,对于函数来 说是局部的,局部变量仅仅在执行定义它的函数时有效。如果 命名覆盖——个局部变量与一个全局变量有相同的名字——在函数执行的时候,局部变量将覆盖全局变量。

例如:

packagemain
vara=6
funcmain(){
p()
q()
p()
f()
p()
}

funcp(){
print(a)
}
funcq(){
a:=5
print(a)
}
funcf(){
a=3
print(a)
}

打印结果:65633

解释:函数q()中对a做了定义,此时a的有效范围就是q()内,而函数f()中,a = 3全局有效的a重新赋值了。

当函数调用函数时,作用域又是怎样的呢?来看下面这个例子:

packagemain

varaint

funcmain(){
a=5
print(a)
f()
}
funcf(){
a:=3
print(a)
g()
}
funcg(){
print(a)
}

打印结果:535

解释: 因为局部变量仅仅在执行定义它的函数时有效,所以g()中的a使用的是外部定义的全局变量。

四、多值返回

和Python一样,Go也支持函数和方法返回多个值。

例如:

func manyvaluereturn(x,y int) (int,int){

return x,x+y

}

调用:

x,z := manyvaluereturn(4,6)

fmt.Printf("x=%d,z=%d",x,z)

执行结果:x=4,z=10

五、命名返回值

Go函数的返回值或者结果参数可以指定一个名字,并且像原始的变量那样使用,如同输入参数一般。如果对其命名,在函数开始时,它们会用其类型的零值初始化;如果函数在不加参数的情况下执行了 return 语句,结果参数的当前值会作为返回值返回。返回值的名字不是强制的,但是它们可以使得代码更加健壮和清晰。

例如:

示例一(没有命名返回值):
funcFactorial(xint)int{
ifx==0{
return1
}else{
returnx*Factorial(x-1)
}
}
示例一(命名了返回值):
funcFactorial(xint)(resultint){
ifx==0{
return=1
}else{
return=x*Factorial(x-1)
}
return
}

对比示例一和示例二,哪种看起来更加清晰明白呢?

六、变参

变参:接受不定数量的参数的函数称为变参函数。例如:func funcname(arg ...int){},arg ...int表示这个函数接受变参,其参数类型全部是int,变量arg是一个int类型的slice。

七、匿名函数与闭包

1、匿名函数定义:不需要定义函数名的一种函数实现方式。

2、Go语言支持随时在代码中定义匿名函数。

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

例如:

packagemain
import"fmt"
funcmain(){
func(x,yint){//函数直接执行
fmt.Println(x+y)
}(5,6)//这里的参数列表表示函数调用
f:=func(x,yint)int{//匿名函数作为值赋值给f
returnx*y
}
result:=f(8,10)
fmt.Printf("result=%d",result)
}

4、闭包的概念: 闭包是可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块内或者任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含在代码块中,所以这些自由变量以及它们引用的对象没有被释放)为自由变量提供绑定的计算环境(作用域)。

5、闭包的价值:闭包的价值在于可以作为函数对象或者匿名函数,对于类型系统而言,这意味着不仅要表示 数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这些函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。

6、Go语言的闭包函数示例:

funcclosefunc(){
varjint=5
a:=func()(func()){
variint=10
returnfunc(){
fmt.Printf("i,j:%d,%d\n",i,j)
}
}()
a()
j*=2//修改j的值
a()
}

执行结果:

i,j : 10,5

i,10

说明:

1)变量a指向的闭包函数引用了局部变量j(closefunc的局部变量)和i(匿名函数的局部变量),i的值被隔离在匿名函数内,在闭包外不能修改。改变j的值,再次调用a,得到的结果是修改后的值。

2)在变量a指向的闭包函数中,只有内部的匿名函数有权访问变量i,因此保证了i的安全性。

八、函数作为值

可以把函数当成值赋值给一个变量。

例如:a := func() { //这里是一个匿名函数

println("Hello!")

}

九、错误处理

1、error接口

Go语言中引入了一个关于错误处理的标准模式,即error接口。

对于大多数函数,如果要返回错误,大致可以定义为如下模式,将error作为多种返回值的最后一个(并非强制的)。

func Foo(param int) (n int,err error) {}

调用是的代码建议按如下方式处理错误情况:

n,err := Foo(0)

if err != nil {

//错误处理

} else {

//使用返回值n

}

我们还可以自定义error类型,在此暂不介绍。

2、defer

一个函数中可以存在多个defer语句,因此需要注意的是,defer语句的调用是遵照先进后出的原则,即最后一个defer语句将最先被执行。

3、Panic(恐慌)和Recover(恢复)

1)Go 没有像 Java 那样的异常机制:不能抛出一个异常。作为替代,它使用了恐慌和恢 复(panic-and-recover)机制。

2)在代码中应当没有或者很少令人恐慌的东西。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


类型转换 1、int转string 2、string转int 3、string转float 4、用户结构类型转换
package main import s "strings" import "fmt" var p = fmt.Println func main() { p("Contains: ", s.Contains("test&quo
类使用:实现一个people中有一个sayhi的方法调用功能,代码如下: 接口使用:实现上面功能,代码如下:
html代码: beego代码:
1、读取文件信息: 2、读取文件夹下的所有文件: 3、写入文件信息 4、删除文件,成功返回true,失败返回false
配置环境:Windows7+推荐IDE:LiteIDEGO下载地址:http://www.golangtc.com/downloadBeego开发文档地址:http://beego.me/docs/intro/ 安装步骤: 一、GO环境安装 二、配置系统变量 三、Beego安装 一、GO环境安装 根
golang获取程序运行路径:
Golang的文档和社区资源:为什么它可以帮助开发人员快速上手?
Golang:AI 开发者的实用工具
Golang的标准库:为什么它可以大幅度提高开发效率?
Golang的部署和运维:如何将应用程序部署到生产环境中?
高性能AI开发:Golang的优势所在
本篇文章和大家了解一下go语言开发优雅得关闭协程的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。1.简介本文将介绍首先为什么需要主...
这篇文章主要介绍了Go关闭goroutine协程的方法,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。1.简介本文将介绍首先为什么需要主动关闭gor...
本篇文章和大家了解一下go关闭GracefulShutdown服务的几种方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。目录Shutdown方法Regi...
这篇文章主要介绍了Go语言如何实现LRU算法的核心思想和实现过程,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。GO实现Redis的LRU例子常
今天小编给大家分享的是Go简单实现多租户数据库隔离的方法,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会...
这篇“Linux系统中怎么安装NSQ的Go语言客户端”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希
本文小编为大家详细介绍“怎么在Go语言中实现锁机制”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么在Go语言中实现锁机制”文章能帮助大家解决疑惑,下面...
今天小编给大家分享一下Go语言中interface类型怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考