004 GO-高级数据类型-(函数)
http://note.youdao.com/noteshare?id=dc1c22a1529a1bcd7956750dc00ff66e&sub=2A57DEF9F7FB40E387A15E9C52E85C14
注意:
一个包内的函数如果以小写开头,只能在包内部使用。想要外部使用(别的包中)必须要大写开头。
感悟:
注意: 函数类型、函数。 类似于 类——和对象的概念(只包含了一个方法的类,不可以定义属性),需要在用函数实现函数类型的时候 ,保持 参数类型、参数名称一致,即为此函数类型 的实现。
否则如果函数类型不实现是 无法使用的,没有任何代码功能。
一、定义和特点
在Go语言中,函数是一等(first-class)类型。这意味着,我们可以把函数作为值来传递和使用。函数代表着这样一个过程:它接受若干输入(参数),并经过一些步骤(语句)的执行之后再返回输出(结果)。特别的是,Go语言中的函数可以返回多个结果。
1.1 声明方式一(匿名函数类型、无名称的返回参数[省略了括号])
func(input1 string ,input2 string) string
/*
1、省略了函数名
2、返回结果参数只有一个,并且省略名称,就省略了括号
*/
1.2 声明方式二(type 函数类型声明)
type MyFunc func(input1 string ,input2 string) string
1.3 函数值(简称-函数)
1.3.1 函数的声明
函数值(或简称函数)的写法与此不完全相同。编写函数的时候需要先写关键字func和函数名称,后跟参数声明列表和结果声明列表,最后是由花括号包裹的语句列表。例如:
func myFunc(part1 string, part2 string) (result string) { result = part1 + part2 return }
我们在这里用到了一个小技巧:如果结果声明是带名称的,那么它就相当于一个已被声明但未被显式赋值的变量。我们可以为它赋值且在return语句中省略掉需要返回的结果值。至于什么是return语句,我就不用多说了吧。显然,该函数还有一种更常规的写法:
func myFunc(part1 string, part2 string) string { return part1 + part2 }
注意,函数myFunc是函数类型MyFunc的一个实现。实际上,只要一个函数的参数声明列表和结果声明列表中的数据类型的顺序和名称与某一个函数类型完全一致,前者就是后者的一个实现。
1.3.2 函数类型的实现
注意: 只要函数的参数声明列表、结果声明列表 的数据类型的顺序和名称 与 某一个函数类型完全一致,那么 这个函数就是这个函数类型的实现。
1.3.3 函数实现的实例
type MyFunc func(input1 string ,input2 string) string
var splice func(string, string) string // 等价于 var splice MyFunc 然后把函数myFunc赋给它: splice = myFunc 如此一来,我们就可以在这个变量之上实施调用动作了: splice("1", "2") 实际上,这是一个调用表达式。它由代表函数的标识符(这里是splice)以及代表调用动作的、由圆括号包裹的参数值列表组成。
如果你觉得上面对splice变量声明和赋值有些啰嗦,那么可以这样来简化它: var splice = func(part1 string, part2 string) string { return part1 + part2 } |
1.3.4 匿名函数
var splice = func(part1 string, part2 string) string { return part1 + part2 }
在这个示例中,我们直接使用了一个匿名函数来初始化splice变量。顾名思义,匿名函数就是不带名称的函数值。匿名函数直接由函数类型字面量和由花括号包裹的语句列表组成。注意,这里的函数类型字面量中的参数名称是不能被忽略的。
其实,我们还可以进一步简化——索性省去splice变量。既然我们可以在代表函数的变量上实施调用表达式,那么在匿名函数上肯定也是可行的。因为它们的本质是相同的。后者的示例如下:
var result = func(part1 string, part2 string) string { return part1 + part2 }("1", "2")
可以看到,在这个匿名函数之后的即是代表调用动作的参数值列表。注意,这里的result变量的类型不是函数类型,而与后面的匿名函数的结果类型是相同的。
1.3.5 函数的调用
splice("1", "2")
var result = func(part1 string, part2 string) string { return part1 + part2 }("1", "2")
匿名函数 调用 :在函数定义结尾用 () 进行调用
1.3.6 函数类型的零值是 nil
1.3.7 函数示例
package main
import ( "fmt" "strconv" "sync/atomic" )
// 员工ID生成器 type EmployeeIdGenerator func(company string, department string, sn uint32) string
// 默认公司名称 var company = "Gophers"
// 序列号 var sn uint32
// 生成员工ID func generateId(generator EmployeeIdGenerator, department string) (string, bool) { // 这是一条 if 语句,我们会在下一章讲解它。 // 若员工ID生成器不可用,则无法生成员工ID,应直接返回。 if generator == nil { return "", false } // 使用代码包 sync/atomic 中提供的原子操作函数可以保证并发安全。 newSn := atomic.AddUint32(&sn, 1) return generator(company, department, newSn), true }
// 字符串类型和数值类型不可直接拼接,所以提供这样一个函数作为辅助。 func appendSn(firstPart string, sn uint32) string { return firstPart + strconv.FormatUint(uint64(sn), 10) }
func main() { var generator EmployeeIdGenerator generator= func (company string, department string, sn uint32) string{ return appendSn((company + "-" + department + "-"), sn) } fmt.Println(generateId(generator, "RD")) } |