日期:2014年7月29日
 
1、函数定义: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 不允许函数嵌套。然而你可以利用匿名函数实现它。
 
2、函数递归的例子
func rec(i int) {
 if i == 10 {
  return
 }
 rec(i+1)
 fmt.Printf("%d ",i)
}
 
3、函数的作用域
    在 Go 中,定义在函数外的变量是全局的,那些定义在函数内部的变量,对于函数来 说是局部的,局部变量仅仅在执行定义它的函数时有效。如果命名覆盖——一个局部变量与一个全局变量有相同的名字——在函数执行的时候,局部变量将覆盖全局变量。
    例如:
          package main
var a = 6
func main() {  
    p() 
    q()
    p()
    f()
    p()
}
 
func p() {
    print(a)
}
func q() {
    a := 5
    print(a)
}
func f() {
    a = 3
    print(a)
}
打印结果:65633
解释:函数q()中对a做了定义,此时a的有效范围就是q()内,而函数f()中,a = 3全局有效的a重新赋值了。
 
当函数调用函数时,作用域又是怎样的呢?来看下面这个例子:
package main
 
var a int
 
func main() {
 a = 5
 print(a)
 f()
}
func f() {
 a := 3
 print(a)
 g()
}
func g() {
 print(a)
}
打印结果:535
解释: 因为局部变量仅仅在执行定义它的函数时有效,所以g()中的a使用的是外部定义的全局变量。
 
4、多值返回:和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
 
5、命名返回值
    Go 函数的返回值或者结果参数可以指定一个名字,并且像原始的变量那样使用,如同输入参数一般。如果对其命名,在函数开始时,它们会用其类型的零值初始化;如果函数在不加参数的情况下执行了 return 语句,结果参数的当前值会作为返回值返回。返回值的名字不是强制的,但是它们可以使得代码更加健壮和清晰。
    例如:
示例一(没有命名返回值):
func Factorial(x int) int {
  if x==0 {
   return 1
  } else {
   return x * Factorial(x-1)
  }
 }
示例一(命名了返回值):
func Factorial(x int) (result int) {
  if x==0 {
   return=1
  } else {
   return = x * Factorial(x-1)
  }
  return
 }
 
对比示例一和示例二,哪种看起来更加清晰明白呢?
 
6、变参:接受不定数量的参数的函数称为变参函数。例如:func funcname(arg ...int){},arg ...int表示这个函数接受变参,其参数类型全部是int,变量arg是一个int类型的slice。
 
7、匿名函数与闭包
1)匿名函数定义:不需要定义函数名的一种函数实现方式。
2)Go语言支持随时在代码中定义匿名函数。
3)匿名函数可以直接赋值给一个变量或者直接执行
例如:
package main
 
import "fmt"
 
func main() {
 func(x,y int) { //函数直接执行
  fmt.Println(x + y)
 } (5,6) //这里的参数列表表示函数调用
 
 f := func(x,y int) int { //匿名函数作为值赋值给f
  return x * y
 }
 
 result := f(8,10)
 fmt.Printf("result=%d",result)
}
 
4)闭包的概念: 闭包是可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块内或者任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含在代码块中,所以这些自由变量以及它们引用的对象没有被释放)为自由变量提供绑定的计算环境(作用域)。
5)闭包的价值:闭包的价值在于可以作为函数对象或者匿名函数,对于类型系统而言,这意味着不仅要表示 数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这些函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。
6)Go语言的闭包函数示例:
func closefunc () {
 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 //修改j的值
 a()
}
执行结果:
i,j : 10,5
i,j : 10,10
 
说明:
(1)变量a指向的闭包函数引用了局部变量j(closefunc的局部变量)和i(匿名函数的局部变量),i的值被隔离在匿名函数内,在闭包外不能修改。改变j的值,再次调用a,得到的结果是修改后的值。
(2)在变量a指向的闭包函数中,只有内部的匿名函数有权访问变量i,因此保证了i的安全性。
 
8、函数作为值
可以把函数当成值赋值给一个变量。
例如:a := func() { //这里是一个匿名函数
               println("Hello!")
           }
 
9、错误处理
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
(1)一个函数中可以存在多个defer语句,因此需要注意的是,defer语句的调用是遵照
先进后出的原则,即最后一个defer语句将最先被执行。
3)Panic(恐慌)和Recover(恢复)
(1)Go 没有像 Java 那样的异常机制:不能抛出一个异常。作为替代,它使用了恐慌和恢 复(panic-and-recover)机制。
(2)在代码中应当没有或者很少令人恐慌的东西。
 

Go语言学习笔记(五) [函数]的更多相关文章

  1. Go语言学习笔记五: 条件语句

    Go语言学习笔记五: 条件语句 if语句 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } 竟然没有括号,和python很像.但是有大括号,与python又不一样. 例子: pa ...

  2. Go语言学习笔记(7)——函数和方法

    Go语言中同时有函数和方法! 函数: go程序必须要包含一个main函数.main函数不能有任何参数和返回值! 1. 定义方法示例: func max(num1, num2 int) int { // ...

  3. 【Go语言学习笔记】函数做参数和闭包

    函数做参数 在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型.类似于重写(同名覆盖). 回调函数:函数有一个参数是函数类型,这个 ...

  4. Python学习笔记(五)函数和代码复用

    函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Python提供了许多内建函数,比如print().同样,你也可以自己创建函数, ...

  5. C语言学习笔记之函数指针与函数指针数组

    指针函数:本质是一个函数: 是一个返回指针类型的函数int * sum(){ } 函数指针:本质是一个指针: 是一个指向函数的指针 int (*p)(int,int) = sum; p(5,6); i ...

  6. C语言学习笔记--字符串函数

    字符串函数 需要包含头文件#include<stdio.h> strlen strcmp strcpy strchr strstr strcasestr

  7. python学习笔记(五)---函数与类

    函数 def为定义函数的一个标志 demo1: def greet_user(username): print("Hello, " + username.title() + &qu ...

  8. [C语言学习笔记五]复合语句和操作符的区分

    复合语句的概念和用法 在部分时候,语句必须要与其他语句相结合才能实现应有的功能.放在花括号 {} 里的代码叫做复合语句. 例如: int a,b; if (a == b) ... ... /* 这一部 ...

  9. JS学习笔记 (五) 函数进阶

    1.函数基础 1.1 函数的基本概念 函数是一段JavaScript代码,只被定义一次,但是可以被调用或者执行许多次.函数是一种对象,可以设置属性,或调用方法. 函数中的参数分为实参和形参.其中,形参 ...

随机推荐

  1. Python3学习(1)——初步了解

    Python是解析性语言,Python解释器将源程序解释并执行. 基本语法 print()   --打印字符串 -直接打印 print("hello world") 结果: hel ...

  2. Python开发——13.操作系统、进程和线程

    一.操作系统 1.定义 操作系统是用来协调.管理和控制计算机硬件和软件资源的系统程序,它位于硬件和应用程序之间.操作系统运行在内核态,拥有对所有硬件的完全访问权,可以执行机器能够运行的任何指令.软件的 ...

  3. Django积木块十——全文检索

    全文检索 全文检索效率更高,对中文可以进行分词 <!--# 1.安装包--> pip install django-haystack pip install whoosh pip inst ...

  4. 最近一个dish项目的建设思考

    系统通用能力的沉淀:a.核心模型的数据沉淀 b.通用服务能力的沉淀 ps1:以前重心主要放在了业务的抽象和通过设计模式来增加可复用的扩展性.局限在于,抽象的范围会被单个业务或者当前的业务所束缚,在更大 ...

  5. 我的C#跨平台之旅(四):使用AOP(filter、attribute)进行系统增强

    1.使用OData提速REST API开发 引入NuGet包:Microsoft.AspNet.WebApi.OData 在启动类中添加如下配置(示例为全局配置,也可基于Controller或Acti ...

  6. shell指令(一)

    ubuntu桌面窗口下进入shell窗口:Ctrl + Alt + F2~F6:  退出shell窗口:Ctrl + Alt + F7:从UI中进入UI命令窗口,Ctrl + Alt +T shell ...

  7. JAVA主流框架---SSM整合

      1.通过监听器的形式引入spring 2.SpringMVC容器和Spring容器间的关系 3.汇通的主旨 让大家熟练掌握SSM调用过程.并且将后台调用彻底掌握. 4.传统项目的搭建的弊端 1.传 ...

  8. 手把手教你Chrome浏览器安装Postman(含下载云盘链接)【转载】

    转载自:http://www.ljwit.com/archives/php/278.html 说明: Postman不多介绍,是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件.本文主要 ...

  9. 【洛谷4172】 [WC2006]水管局长(LCT)

    传送门 洛谷 BZOJ Solution 如果不需要动态的话,那就是一个裸的最小生成树上的最大边权对吧. 现在动态了的话,把这个过程反着来,就是加边对吧. 现在问题变成了怎么动态维护加边的最小生成树, ...

  10. 小白必读:闲话HTTP短连接中的Session和Token

    本文引用了刘欣的文章,感谢原作者的分享. 1.引言 Http协议在现今主流的IM系统中拥有无可替代的重要性(在IM系统中用HTTP发起的连接被大家简称为http短连接),但Http作为传统互联网信息交 ...