1.函数签名
函数签名其实就是函数的参数列表和结果列表的统称,它定义了可用来鉴别不同函数的特征,同时也定义了与函数交互的方式。注意:各个参数结果和结果的名称不能算作函数签名的一部分,甚至对于结果声明来说,没有名称都可以。只有两个函数的参数列表和结果列表中的元素顺序及其类型是一致的,那么就可以说它们是一样的函数或者实现了同一函数类型的函数。
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")
}
2.高阶函数
高阶函数可以满足以下两个条件:
- 接收其他的函数作为参数传入
- 把其他的函数作为结果返回
package main
import (
"errors"
"fmt"
)
type operate func(x, y int) int
func calculate(x int, y int, op operate) (int, error) {
if op == nil {
return 0, errors.New("invalid operation")
}
return op(x, y), nil
}
type calculateFunc func(x int, y int) (int, error)
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
}
}
func main() {
x, y := 12, 23
op := func(x, y int) int {
return x + y
}
result, err := calculate(x, y, op)
fmt.Printf("The result: %d (error: %v)\n",
result, err)
result, err = calculate(x, y, nil)
fmt.Printf("The result: %d (error: %v)\n",
result, err)
x, y = 56, 78
add := genCalculator(op)
result, err = add(x, y)
fmt.Printf("The result: %d (error: %v)\n",
result, err)
}
在函数内修改传入函数的参数值,那么源数据会被修改吗?
- 对于数组这类值类型数据,传给函数的参数值都会被复制,函数在其内部使用的并不是参数的原值而是它的副本
- 对于引用类型,例如:切片、字典、通道,会像上面一样复制它们的值,只会拷贝它们本身并不会拷贝它们引用的底层数据,也就说此时是浅表复制不是深层复制
package main
import "fmt"
func main() {
array1 := [3]string{"a", "b", "c"}
fmt.Printf("The array: %v\n", array1)
array2 := modifyArray(array1)
fmt.Printf("The modified array: %v\n", array2)
fmt.Printf("The original array: %v\n", array1)
fmt.Println()
slice1 := []string{"x", "y", "z"}
fmt.Printf("The slice: %v\n", slice1)
slice2 := modifySlice(slice1)
fmt.Printf("The modified slice: %v\n", slice2)
fmt.Printf("The original slice: %v\n", slice1)
fmt.Println()
}
func modifyArray(a [3]string) [3]string {
a[1] = "x"
return a
}
func modifySlice(a []string) []string {
a[1] = "i"
return a
}
3.思考题
(1)complexArray1被传入函数的话,这个函数中对该参数值的修改会影响到它的原值吗?
package main
import "fmt"
func main() {
complexArray1 := [3][]string{
[]string{"d", "e", "f"},
[]string{"g", "h", "i"},
[]string{"j", "k", "l"},
}
fmt.Printf("The complex array: %v\n", complexArray1)
complexArray2 := modifyComplexArray(complexArray1)
fmt.Printf("The modified complex array: %v\n", complexArray2)
fmt.Printf("The original complex array: %v\n", complexArray1)
}
func modifyComplexArray(a [3][]string) [3][]string {
a[1][1] = "s"
a[2] = []string{"o", "p", "q"}
return a
}
The complex array: [[d e f] [g h i] [j k l]]
The modified complex array: [[d e f] [g s i] [o p q]]
The original complex array: [[d e f] [g s i] [j k l]]
(2)函数真正拿到的参数值其实只是它们的副本,那么函数返回给调用方的结果值也会被复制
吗?
答:是复制的
本节示例代码地址:demo Github