Go语言入门(13)-map
map是Go提供的另外一种集合,他可以:
①将key映射到value;
②快速通过key找到对应的value;
同时,它的key几乎可以是任何类型。
声明map,必须指定key和value的类型:
下面来看一个简单的例程,在该例程中,是将温度的数值通过映射的方式传递给值名,在需要调取数字的时候,直接调取值名即可:
package mainimport ("fmt"
)func main() {temperature := map[string]int{"Earth": 15,"Mars": -65,}temp := temperature["Earth"]fmt.Printf("On average the Earth is %v° C.\n", temp)fmt.Println(temp)temperature["Earth"] = 16temperature["Venus"] = 464fmt.Println(temperature)moon := temperature["Moon"]fmt.Println(moon)
}
运行结果如下:
数组、int、float64等类型在赋值给新变量or传递至函数/方法时,会创建相应的副本(可以理解为复制一份原来函数/方法,并对这个复制的副本进行操作),但map不会创建(复制)。
package mainimport ("fmt"
)func main() {planets := map[string]string{"Earth": "Sector ZZ9","Mars": "Sector ZZ9",}planetsMarkII := planetsplanets["Earth"] = "whoops"fmt.Println(planets)fmt.Println(planetsMarkII)delete(planets, "Earth")fmt.Println(planetsMarkII)fmt.Println(planets)
}
运行上述代码,结果如下:
在前面几节我们讲过make函数如何进行预分配,现在要讲如何使用make函数对map进行预分配。
首先要知道的是,除非使用符合字面值来初始化map,否则必须使用内置的make函数来为map分配空间。
其次,在创建map时,make函数可接受一个或两个参数(第二个参数用于为指定数量的key预先分配空间)
使用make函数创建的map,初始长度为0:
下面着重介绍一下if ok语句。它与if else语句类似,可以在此判断语句内定义变量:下面看一个简单的例子:
if moon, ok := temperature["Moon"]; ok {fmt.Println("On average the moon is %v° C.\n", moon)} else {fmt.Println("where is the moon?")}
这个例子中的if ok语句用于判断:从map中取值是否存在。很显然,在上述例子中并没有事先定义这个map,所以该判断语句执行的是else后的内容。
if ok语句除了这个作用,还有其他两个主要的作用:
①在处理接口类型时,使用类型断言可以判断接口变量实际保存的类型。
var i interface{} = "hello"if s, ok := i.(string); ok {fmt.Println("i 是字符串类型,内容是:", s)
} else {fmt.Println("i 不是字符串类型")
}
i.(string)
是类型断言。- 如果接口
i
实际保存的是string
类型,则ok
为true
,否则为false
。 - 这种方式是“逗号 ok”用法在类型断言中的体现。
②从 channel 接收值判断是否关闭
从 channel 接收值时,也可以通过第二个返回值“ok”来判断 channel 是否已经关闭。
ch := make(chan int)
go func() {ch <- 42close(ch)
}()if value, ok := <-ch; ok {fmt.Println("接收到值:", value)
} else {fmt.Println("channel 已关闭且没有值可接收")
}
<-ch
返回两个值:接收到的值和一个布尔值ok
。- 如果 channel 还未关闭且有值,则
ok
为true
。 - 如果 channel 被关闭且没有值可接收,则
ok
为false
。
最后再看一个案例:使用map和slice实现数据分组
package mainimport ("fmt""math"
)func main() {temperatures := []float64{-28.0, 32.0, -31.0, -29.0, -23.0, -29.0, -28.0, -33.0,}groups := make(map[float64][]float64)for _, t := range temperatures {g := math.Trunc(t/10) * 10 //math.Trunc(xx):把Trunc内数值的小数位去掉groups[g] = append(groups[g], t)}for g, temperatures := range groups {fmt.Printf("%v: %v\n", g, temperatures)}
}