一、map数据类型

1.1 声明和定义

map类型是一个key-value的数据结构,又叫字典。(map也是可以扩容的,内部自动扩容)

声明:

var map1 map[keytype]valuetype

例子:

//var a map[key的类型]value类型
var a map[string]int
var b map[int]string
var c map[float32]string

注意:

1.声明是不会分配内存的,需要make初始化。

2.map必须初始化才能使用,否则panic。

3.map中声明value是什么类型,就存什么类型,混合类型自身不支持(Go是强类型语言),interfice支持存混合类型数据。

map类型的变量默认初始化为nil,所以需要使用make分配map内存然后才能使用,不然会panic(异常)。

实例如下:

实例1-1

package main

import (
"fmt"
) func main() {
var a map[string]int
if a == nil { //map未初始化,其初始默认为nil
fmt.Println("map is nil. Going to make one.")
a = make(map[string]int)
}
}

执行结果如下:

另外也验证一下不初始化跑出panic

实例如下:

实例1-2

package main

import (
"fmt"
) func main() {
var user map[string]int
user["abc"] =
fmt.Println(user)
}

执行结果如下:

已经抛出了panic,所以必须要初始化。

1.2 插入操作

代码示例如下:

实例1-3

package main

import (
"fmt"
) func main() {
a := make(map[string]int)
a["steve"] =
a["jamie"] =
a["mike"] =
fmt.Println("a map contents:", a)
}

执行结果如下:

1.3 初始化

第一种:make

实例1-4

package main

import (
"fmt"
) func main() {
var user map[string]int = make(map[string]int, ) //初始化时可以指定容量也可以不指定,指定的话可以提升性能
//user := make(map[string]int) //也可以写成这样,多种方式
user["abc"] =
fmt.Println(user)
}

执行结果如下:

第二种:声明时进行初始化(借助常量)

实例1-5

package main

import (
"fmt"
) func main() {
a := map[string]int{
"steve": ,
"jamie": ,
}
a["mike"] =
fmt.Println("a map contents:", a)
}

执行结果如下:

1.4 map扩容

map扩容实际上类似切片扩容就是:

map本来的容量是4,现在容量不够了,map内部自动扩容,比如说扩容到8,其在底层的机制就是将旧的内存地址中的4个元素拷贝到新到容量为8的内存地址中,然后再继续接收新元素并使用。

所以说:在初始化时,如果我们知道map大概有多少元素时,可以初始化时指定,这样可以在一定程度上提升性能(频繁扩容影响性能)

1.5如何访问map中元素?

通过key访问map中的元素

实例1-6

package main

import "fmt"

func main() {
a := map[string]int{
"steve": ,
"jamie": ,
}
a["mike"] =
b := "jamie"
fmt.Println("Salary of", b, "is", a[b])
}

执行结果如下:

1.6 如何判断map指定的key是否存在?

相当于做一个白名单,去判断map中指定key是否存在。

格式:value, ok := map[key]

注意:ok仅仅是个变量,可以随便命名

实例1-7    实例1:

package main

import (
"fmt"
) func main() {
a := map[string]int{
"steve": ,
"jamie": ,
}
a["mike"] =
b := "joe"
value, ok := a[b] //ok仅仅是个变量,可以随便命名
if ok == true {
fmt.Println("Salary of", b, "is", value)
} else {
fmt.Println(b, "not found")
}
}

执行结果如下:

实例1-8  实例2  (用户白名单基础版)

package main

import (
"fmt"
) var whiteUser map[int]bool = map[int]bool{
: true,
: true,
: true,
} func isWhiteUser(userId int) bool {
_, ok := whiteUser[userId] //这里不需要返回value,所以直接_忽略
return ok
} func main() {
userId :=
if isWhiteUser(userId) {
fmt.Printf("is white user:%v\n", userId)
} else {
fmt.Printf("is normal user:%v\n", userId)
}
}

执行结果如下:

1.7 map遍历操作

其实就是用for range

range返回key value并赋值给变量,结合数组、切片遍历也是for range,其实数组及切片就是个特殊map。

代码示例如下:

实例1-9

package main

import (
"fmt"
) func main() {
a := map[string]int{
"steve": ,
"jamie": ,
}
a["mike"] =
fmt.Println("All items of a map")
for key, value := range a {
fmt.Printf("personSalary[%s] = %d\n", key, value)
}
}

执行结果如下:

1.8 map删除元素

借助一个delete内置函数,delete指定map的key即可删除

代码示例如下:

实例1-10

package main

import (
"fmt"
) func main() {
a := map[string]int{
"steve": ,
"jamie": ,
}
a["mike"] =
fmt.Println("map before deletion", a)
delete(a, "steve")
fmt.Println("map after deletion", a)
}

执行结果如下:

1.9 map的长度

借助len函数

实例1-11

package main

import (
"fmt"
) func main() {
a := map[string]int{
"steve": ,
"jamie": ,
}
a["mike"] =
fmt.Println("length is", len(a))
}

执行结果如下:

1.10 map是引用类型

通过下面这个例子验证map是引用类型

实例1-12

package main

import (
"fmt"
) func main() {
a := map[string]int{
"steve": ,
"jamie": ,
}
a["mike"] =
fmt.Println("origin map", a)
b := a
b["mike"] =
fmt.Println("a map changed", a)
}

执行结果如下:

解释:

可以发现a为map,将a赋值给b,b也是map,map b做了修改,此时打印a,map a也发生了变化,这证明map是引用类型

1.11 map排序

默认情况下, map并不是按照key有序进行遍历的。

千万不要依赖map中的顺序,map是无序的(go1.6之前好像是有序的)

可见如下实例:

实例1-13

package main

import (
"fmt"
) func main() {
var a map[string]int = make(map[string]int, )
for i := ; i < ; i++ {
key := fmt.Sprintf("key%d", i)
a[key] = i
}
for key, value := range a {
fmt.Printf("key:%s = %d\n", key, value)
}
}

执行结果如下:

但是如何map如何按照key进行排序

思路:先把key排序,然后再按照排序后的key去遍历map

代码示例如下:

实例1-14

package main

import (
"fmt"
"sort"
) func main() {
var a map[string]int = make(map[string]int, )
for i := ; i < ; i++ {
key := fmt.Sprintf("key%d", i)
a[key] = i
}
var keys []string //将无序的map的key放入到切片中
for key, _ := range a {
keys = append(keys, key)
}
sort.Strings(keys) //借助sort进行排序
for _, key := range keys { //将切片进行遍历
fmt.Printf("key:%s=%d\n", key, a[key])
}
}

执行结果如下:

1.12 map类型切片

首先需要先将切片初始化,切片中的每一个元素又是一个map,所以要使用map时,又需要对每一个元素进行一次初始化(引用类型)

实例1-15    实例1

package main

import (
"fmt"
) func mapSlince() { } func main() {
var s []map[string]int //s是一个map类型的切片
s = make([]map[string]int, ) //切片初始化 for k, v := range s {
fmt.Printf("index:%d val:%v\n", k, v)
} s[] = make(map[string]int, ) //map初始化
s[]["abc"] = for key, val := range s[] {
fmt.Printf("key:%s value:%v\n", key, val)
}
}

执行结果如下:

实例1-16  实例2

package main

import (
"fmt"
) func main() {
var mapSlice []map[string]int
mapSlice = make([]map[string]int, ) //此时是一个未初始化的map类型切片,所以需要先将切片初始化
fmt.Println("before map init")
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
}
fmt.Println()
mapSlice[] = make(map[string]int, ) //要使用map,需要将map进行初始化。
mapSlice[]["a"] =
mapSlice[]["b"] =
mapSlice[]["c"] =
mapSlice[]["d"] =
mapSlice[]["e"] =
fmt.Println("after map init")
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
}
}

执行结果如下:

Go语言基础之6--map(字典)数据类型的更多相关文章

  1. 语言基础:C#输入输出与数据类型及其转换

    今天学习了C#的定义及特点,Visual Studio.Net的集成开发环境和C#语言基础. C#语言基础资料——输入输出与数据类型及其转换 函数的四要素:名称,输入,输出,加工 输出 Console ...

  2. 01 C语言程序设计--01 C语言基础--第3章 基本数据类型01

    01.1.3.1序言 00:02:17 01.1.3.2 C语言中的基本元素和常量的概念 00:08:54 01.1.3.3示例--常量 00:12:08 01.1.3.4变量的概念和命名规则 00: ...

  3. 第二章(java程序设计)第三章(语言基础)

    第二章 2.1 对象 对象的概念是由现实世界引入问题模型: 对象包含有:状态和行为.具体地来说是: 数据封装:对象的方法的作用就是:将内部变量封装起来,提供给外界交互的窗口.(实现对数据的隐藏) 继承 ...

  4. NDK以及C语言基础语法(一)

    一.什么是NDK? Native Development Kit (本地开发工具包): NDK中提供了一系列的工具,帮助我们快速开发C/C++的动态库,并能自动将so文件和java文件一起打包成apk ...

  5. Go语言基础之数据类型

    Go语言基础之数据类型 Go语言中有丰富的数据类型,除了基本的整型.浮点型.布尔型.字符串外,还有数组.切片.结构体.函数.map.通道(channel)等.Go 语言的基本类型和其他语言大同小异. ...

  6. JavaScript 引入方式 语言规范 语言基础 数据类型 常用方法 数组 if_else 比较运算符 for while 函数 函数的全局变量和局部变量 {Javascript学习}

    Javascript学习 JavaScript概述 ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript ...

  7. Python语言基础-语法特点、保留字与标识符、变量、基本数据类型、运算符、基本输入输出、Python2.X与Python3.X区别

    Python语言基础 1.Python语法特点 注释: 单行注释:# #注释单行注释分为两种情况,例:第一种#用于计算bim数值bim=weight/(height*height)第二种:bim=we ...

  8. Go语言基础之map

    Go语言基础之map Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现. map map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能 ...

  9. C#-语言基础+数据类型+运算符

    一.C#语言基础 新建项目:文件→新建→项目→Visual C#(默认.NET Framework 4.5)→控制台应用程序 1.项目结构 (1)项目后缀 .config ——配置文件(存放配置参数文 ...

随机推荐

  1. C# 把一个文件夹下所有文件删除

    public static void DelectDir(string srcPath){ try { DirectoryInfo dir = new DirectoryInfo(srcPath); ...

  2. Angular问题03 @angular/material版本问题

    1 问题描述 应用使用 angular4在使用@angular/material时,若果在导入模块时使用mat开头,就会报错. 2 问题原因 @angular/material版本出现问题,@angu ...

  3. git push是报Permission denied (publickey)错误解决

    今天晕了半天了,搞了个git工程到github上,以为很简单,因为之前也弄过,那知道搞了大半天都搞不好,一直报如下错误 D:\javawork\ee-0.0.1-SNAPSHOT>git pus ...

  4. ROS Learning-019 learning_tf-03(编程) 添加额外的坐标系 (Python版)

    ROS Indigo learning_tf-03 添加额外的坐标系 (Python版) 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14.0 ...

  5. php学习笔记-continue和break

    这两个关键字经常被用在循环中,但作用是完全不同的. 在循环中遇到continue这个单词的时候一定要理解为skip,跳过或者略过,啥意思?就是跳过本次循环,后面的循环继续走起来,老铁. break是说 ...

  6. loj10093 网络协议

    传送门 分析 第一问我们不难想出是缩点之后的新图中入度为0的点的个数,对于第二问,我们画一画可以发现最优策略就是对于每一个入度为0的点都有一个出度为0的点连向它,而对于每一个出度为0的点也一定连向一个 ...

  7. for与break的用法

    # Auther: Aaron Fan age_of_oldboy = 56 #执行3次循环for i in range(3): guess_age = int(input("猜一下oldb ...

  8. 优先队列详解priority_queue .RP

    ) 删除.在最小优先队列(min priorityq u e u e)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素;对于最大优先队列(max priority queue),查找操作用 ...

  9. shape不同版本这间的兼容

    在做那个只有左边上面是圆角和只有右边下边是圆角的时候,出现了一个问题,那就是在android3.0以前,android:bottomLeftRadius与android:bottomRightRadi ...

  10. 20169219《linux内核原理与分析》第九周作业

    网易云课堂学习 可执行程序的装载 可执行程序的产生过程:预处理-----> 编译 ----> 汇编 ----> 链接 以hello.c文件为例进行分析,编译步骤如下 vi hello ...