GO映射(map)

映射将键映射到值。

映射的零值为 nilnil 映射既没有键,也不能添加键。

make 函数会返回给定类型的映射,并将其初始化备用。

映射的文法与结构体相似,不过必须有键名。

package main

import "fmt"

type Vertex struct {
	Lat, Long float64
}

var m map[string]Vertex

func main() {
	m = make(map[string]Vertex)
	m["Bell Labs"] = Vertex{
		40.68433, -74.39967,
	}
	fmt.Println(m["Bell Labs"])
}
/*
结果:
{40.68433 -74.39967}
*/

若顶级类型只是一个类型名,你可以在文法的元素中省略它。

var m = map[string]Vertex{
	"Bell Labs": {40.68433, -74.39967},
	"Google":    {37.42202, -122.08408},
}

修改映射

​ 在映射 m 中插入或修改元素:

m[key] = elem

​ 获取元素:

elem = m[key]

​ 删除元素:

delete(m, key)

​ 通过双赋值检测某个键是否存在:

elem, ok = m[key]

​ 若 keym 中,oktrue ;否则,okfalse

​ 若 key 不在映射中,那么 elem 是该映射元素类型的零值。

​ 同样的,当从映射中读取某个不存在的键时,结果是映射的元素类型的零值。

:若 elemok 还未声明,你可以使用短变量声明:

elem, ok := m[key]

函数值

​ 函数也是值。它们可以像其它值一样传递。

​ 函数值可以用作函数的参数或返回值。

package main

import (
	"fmt"
	"math"
)

func compute(fn func(float64, float64) float64) float64 {
	return fn(3, 4)
}

func main() {
	hypot := func(x, y float64) float64 {
		return math.Sqrt(x*x + y*y)
	}
	fmt.Println(hypot(5, 12))

	fmt.Println(compute(hypot))
	fmt.Println(compute(math.Pow))
}
/*结果:
13
5
81
*/

函数的闭包

​ Go 函数可以是一个闭包。闭包是一个函数值,它引用了其函数体之外的变量。该函数可以访问并赋予其引用的变量的值,换句话说,该函数被这些变量“绑定”在一起。

​ 例如,函数 adder 返回一个闭包。每个闭包都被绑定在其各自的 sum 变量上。

package main

import "fmt"

func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}

func main() {
	pos, neg := adder(), adder()
	for i := 0; i < 10; i++ {
		fmt.Println(
			pos(i),
			neg(-2*i),
		)
	}
}

练习:斐波纳契闭包

​ 让我们用函数做些好玩的事情。

​ 实现一个 fibonacci 函数,它返回一个函数(闭包),该闭包返回一个斐波纳契数列 (0, 1, 1, 2, 3, 5, ...)

package main

import "fmt"

// 返回一个“返回int的函数”
func fibonacci() func() int {
    //num用来返回也就是当前的数字
	num := 0
    //用来计算当前数字和下一个数字
	num1 := 0
	num2 := 1
	return func() int{
		num = num1
		t := num2
		num2 = num2 + num1
		num1 = t	
		return num
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}