11 Go语言的映射——map

Go语言的映射——map

[TOC]数组

  • 相似其它语言中的哈希表或者字典,以key-value形式存储数据
  • Key必须是支持==或!=比较运算的类型,不能够是函数、map或slice;value 能够是任意类型。
  • Map查找比线性搜索快不少,但比使用索引访问数据的类型慢100倍
  • Map使用make()创 建,支持 := 这种简写方式
  • make(map[keyType]valueType, cap),cap表示容量,可省略
  • 超出容量时会自动扩容,但尽可能提供一个合理的初始值,预先申请内存,有助于提高性能
  • 使用len()获取元素个数
  • 键值对不存在时自动添加,使用delete()删除某键值对
  • 使用 for range 对map和slice进行迭代操做

Map介绍

go语言中的map是一种数据结构,用于存储一些列无序的键值对。map是一个无序的集合,由于它底层是一个hash表(散列表)。map的键只要支持==或!=比较运算的类型均可以,可是不能够是函数,map,slice等不能比较的。value能够是任意的类型。数据结构

一、Map 的建立

1.1 使用make函数函数

// 建立一个映射,键的类型是 string,值的类型是 int
dict := make(map[string]int)

make(map[keyType]valueType, cap),cap表示容量,能够在建立的时候指定一个合理初始的容量大小,这样就会申请一大块内存,避免在后续使用中频繁扩张浪费性能。好比:m := make(map[string]int, 1000) 性能

1.2 使用字面值建立设计

// 建立一个映射,键和值的类型都是 string
// 使用两个键值对初始化映射
dict := map[string]string{"Red": "#da1337", "Orange": "#e95a22"}

二、使用映射

2.1为映射赋值

// 建立一个空映射,用来存储颜色以及颜色对应的十六进制代码
colors:=map[string]string{}
// 将 Red 的代码加入到映射
colors["Red"]="#da1337"

2.1 未初始化的map,赋值报错,即 nil map

// 经过声明映射建立一个 nil 映射
var colors map[string]string
// 将 Red 的代码加入到映射
colors["Red"] = "#da1337"
Runtime Error:
panic: runtime error: assignment to entry in nil map

2.2 从map 中获取值,并判断键是否存在

因为go的多返回值,map获取值的时候,会返回值,和一个boolean的参数,表示成不成功,有没有,对不对。指针

在 Go 语言里,经过键来索引映射时,即使这个键不存在也总会返回一个值。在这种状况下,返回的是该值对应的类型的零值。rest

// 获取键 Blue 对应的值
value, exists := colors["Blue"]// 这个键存在吗?
if exists {
    fmt.Println(value)
}
//固然了也能够直接用 类型的零值来判断----是同样的
// 获取键 Blue 对应的值
value := colors["Blue"]
// 这个键存在吗?
if value != "" {
    fmt.Println(value)
}

2.3 用range迭代map

// 建立一个映射,存储颜色以及颜色对应的十六进制代码
colors := map[string]string{
    "AliceBlue": "#f0f8ff",
    "Coral": "#ff7F50",
    "DarkGray": "#a9a9a9",
    "ForestGreen": "#228b22",
}
// 显示映射里的全部颜色
for key, value := range colors {
    fmt.Printf("Key: %s Value: %s\n", key, value)
}
//

range迭代和数组、slice 都同样,只不过这里返回的是map的键值对,而array ,slice返回的是索引和值code

2.4 map中的delete函数

delete(map,key) 函数能够从map中删除指定key的键值对。这种方法只能用在映射存储的值都是非零值的状况对象

// 删除键为 Coral 的键值对
delete(colors, "Coral")
// 显示映射里的全部颜色
for key, value := range colors {
    fmt.Printf("Key: %s Value: %s\n", key, value)
}

2.5 map做为参数传递

和slice同样,都是引用类型,都是指向了底层数据结构。slice指向的是数组,map指向的是hash表。map在函数之间做为参数传递的时候,是进行map指针的拷贝,相对于指针来讲是值拷贝,相对于底层来讲是引用传递。 其实我以为go全部的传递都是值传递,只不过有的值是值,有的值是指针。索引

因此,在函数中传递map,对map进行修改会对底层数据进行修改。

// removeColor 将指定映射里的键删除
func removeColor(colors map[string]string, key string) {
    delete(colors, key)
}
// 建立一个映射,存储颜色以及颜色对应的十六进制代码
colors := map[string]string{
    "AliceBlue": "#f0f8ff",
    "Coral": "#ff7F50",
    "DarkGray": "#a9a9a9",
    "ForestGreen": "#228b22",
}
// 显示映射里的全部颜色
for key, value := range colors {
    fmt.Printf("Key: %s Value: %s\n", key, value)
}
fmt.Println()
// 调用函数来移除指定的键
removeColor(colors, "Coral")
// 显示映射里的全部颜色
for key, value := range colors {
    fmt.Printf("Key: %s Value: %s\n", key, value)
}
//输出结果
Key: AliceBlue Value: #F0F8FF
Key: Coral Value: #FF7F50
Key: DarkGray Value: #A9A9A9
Key: ForestGreen Value: #228B22

Key: AliceBlue Value: #F0F8FF
Key: DarkGray Value: #A9A9A9
Key: ForestGreen Value: #228B22

map的常见操做

m := map[string]int{
    "a": 1,
}
if v, ok := m["a"]; ok { // 判断 key 是否存在。
    println(v)
}
println(m["c"]) // 对于不存在的 key,直接返回 \0,不会出错。

m["b"] = 2 // 新增或修改。

delete(m, "c") // 删除。若是 key 不存在,不会出错。

println(len(m)) // 获取键值对数量。 cap ⽆效。

for k, v := range m { // 迭代,可仅返回 key。随机顺序返回,每次都不相同。
    println(k, v)
}

三、从map取出的value是一个拷贝,对其成员修改没有意义

type user struct{ name string }
m := map[int]user{     // 当 map 因扩张⽽从新哈希时,各键值项存储位置都会发⽣改变。 所以, map
    1: {"user1"},      // 被设计成 not addressable。 相似 m[1].name 这种指望透过原 value
}                     // 指针修改为员的⾏为⾃然会被禁⽌。
m[1].name = "Tom"     // Error: cannot assign to m[1].name

由于取出的是一个user实例的拷贝,不能直接对其成员修改,若是要实现,能够有两种方式

3.1完整的替换这个value

u := m[1]
u.name = "Tom"
m[1] = u // 替换 value。

3.2 使用指针

m2 := map[int]*user{
    1: &user{"user1"},
}
m2[1].name = "Jack" // 返回的是指针复制品。透过指针修改原对象是容许的。
相关文章
相关标签/搜索