声明关键字:func
示例:
package main
import "fmt"
type Printer func(contents string) (n int, err error)
func printToStd(contents string) (bytesNum int, err error) {
return fmt.Println(contents)
}
func main() {
var p Printer
p = printToStd
p("something")
}
书写函数签名的方式与函数声明的是一致的。只是紧挨在参数列表左边的不是函数名称,而是关键字func。这里函数名称和func互换 了位置。
函数的签名其实就是函数的参数列表和结果列表的统称,它定义了可用来鉴别不同函数的那些特征,同时也定义了我们与函数交互的方式.
各个参数和结果的名称不能算作函数签名的一部分,甚至对于结果声明来说,没有名称都可以。
只要两个函数的参数列表和结果列表中的元素顺序及其类型是一致的,我们就可以说它们是一样的函数,或者说是实现了同一个函数类型的函数。
高阶函数
1. 接受其他的函数作为参数传入;
声明一个名叫operate的函数类型
type operate func(x, y int) int
如果operate类型的参数op为nil,那么就直接返回0和一个代表了具体错误的error类型值。
如果检查无误,那么就调用op并把那两个操作数传给它,最后返回的结果和代表没有错误发生的nil。
func calculate(x int, y int, op operate) (int, error) {
if op == nil {
return 0, errors.New("invalid operation")
}
return op(x, y), nil
}
2. 把其他的函数作为结为结果返回。
x, y = 56, 78
add := genCalculator(op)
result, err = add(x, y)
fmt.Printf("The result: %d (error: %v)\n", result, err)
3.闭包
在一个函数中存在对外来标识符的引用。所谓的外来标识符,既不代表当前函数的任何参数或结果,也不是函数内部声明的,它是直接从从外边拿过来的
func genCalculator(op operate) calculateFunc {
return func(x int, y int) (int, error) {
if op == nil {
return 0, errors.New("invalid operation")
}
return op(x, y), nil
}
}
genCalculator函数只做了一件事,那就是定义一个匿名的、calculateFunc类型的函数并把它作为结果值返回。
这个匿名的函数就是一个闭包函数。它里面使用的变量op既不代表它的任何参数或结果也不是它自己声明的,而是定义它的genCalculator函数被调用的时候确定的。
我们是在动态地生成那部分程序逻辑。
所有传给函数的参数值都会被复制,函数在其内部使用的并不是参数值的原值,而是它的副本
由于数组是值类型,所以每一次复制都会拷贝它,以及它的所有元素值。我在modify函数中修改的只是原数组的副本而已,并不会对原数组造成任何影响。
对于引用类型,比如:切片、字典、通道,像上面那样复制它们的值,只会拷贝它们本身而已,并不会拷贝它们引用的底层数据。也就是说,这时只是浅表复制,而不是深拷贝。