初探Golang(4)-map和流程控制语句

本文探讨了Go语言map的声明、使用方法,如插入、更新和删除操作,以及遍历流程。同时揭示了map的底层实现结构,包括哈希表原理和扩容策略。此外,还介绍了Go的控制结构,如if、switch和for循环,以及值传递与引用传递的区别。
摘要由CSDN通过智能技术生成

1.map

map 是引用类型的,如果声明没有初始化值,默认是nil。空的切片是可以直接使用的,因为他有对应的底层数组,空的map不能直接使用。需要先make之后才能使用。

//1, 声明map 默认值是nil
var m1 map[key_data_type]value_data_type
声明  变量名称 map[key的数据类型]value的数据类型
//2,使用make声明
m2:=make(map[key_data_type]value_data_type)
//3,直接声明并初始化赋值map方法
m3:=map[string]int{"语文":89,"数学":23,"英语":90}

1.1 map 使用

  • 插入以及更新语法:map[key]=value
  • 删除map中key对应的键值对数据 语法: delete(map, key)
  • 访问语法 map[key]


//遍历map
for key, val := range map1 {
    fmt.Println(key, val)
}

1.2 map底层原理

源代码解析

struct Hmap
{
uint8 B; // 可以容纳2^B个项
uint16 bucketsize; // 每个桶的大小
byte *buckets; // 2^B个Buckets的数组
byte *oldbuckets; // 前一个buckets,只有当正在扩容时才不为空
};

struct Bucket
{
uint8 tophash[BUCKETSIZE]; // hash值的高8位....低位从bucket的array定位到bucket
Bucket *overflow; // 溢出桶链表,如果有
byte data[1]; // BUCKETSIZE keys followed by BUCKETSIZE values
};
// BUCKETSIZE是用宏定义的8,每个bucket中存放最多8个key/value对, 如果多于8个,那么会申请一个新的bucket,overflow指向它
  • Bucket中key/value的放置顺序,是将keys放在一起,values放在一起。
  • 扩容使用的是增量扩容:扩容会建立一个大小是原来2倍的新的表,将旧的bucket搬到新的表中之后,并不会将旧的bucket从oldbucket中删除,而是加上一个已删除的标记。当hash表扩容之后,需要将那些旧的pair重新哈希到新的table上,这个工作是逐步的完成(在insert和remove时每次搬移1-2个pair)

查找过程

  1. 根据key计算出hash值。
  2. 如果存在old table, 首先在old table中查找,如果找到的bucket已经evacuated,转到步骤3。 反之,返回其对应的value。
  3. 在new table中查找对应的value。
    插入过程分析
  4. 根据key算出hash值,进而得出对应的bucket。
  5. 如果bucket在old table中,将其重新散列到new table中。
  6. 在bucket中,查找空闲的位置,如果已经存在需要插入的key,更新其对应的value。
  7. 根据table中元素的个数,判断是否grow table。
  8. 如果对应的bucket已经full,重新申请新的bucket作为overbucket。
    将key/value pair插入到bucket中。

2.流程控制

  • 我们的程序的执行正常是由上到下逐行执行,叫做 顺序结构 。
  • 程序中为了满足某种条件的时候才会执行的结构,叫做选择结构(if、 switch)。
  • 当满足条件时候循环反复执行多次的代码, 叫做 循环结构(for)

2.1 if语句

if 布尔表达式{
    //布尔条件为true时候执行代码
}

if 布尔表达式 {
    //条件成立执行代码
}else{
      //条件不成立执行代码
}

if 布尔表达式 {
    //布尔条件为true时候执行代码
}else if 布尔表达式2{
      //布尔条件为flase时候执行代码
}else{
     //上面都不成立执行代码
}

特殊写法:Go语言中可以在if之后,条件判断之间再加上一段执行语句,执行的结果再用作后面的条件判断。(先执行语句,再判断条件)

if a :=1; a==1
{

}

2.2 switch分支语句

if 中判断条件只能为bool类型,但是switch中条件可以为其他类型,case的值必须是唯一的,因为只能进入一个case语句块。

switch 中 break 和fallthrough
break 直接跳出整个switch语句块
fallthrough 当前case执行完了,继续执行下面的case

2.3 for 循环语句

语法: for init; condition;post{ }
init            初始化  只执行一次
condition   bool类型 执行条件 如果满足继续执行后面的循环体  如果不满足 则终止执行
{}               循环体
post           表达式 将在循环体执行结束之后执行

break:跳出当前循环,如果后面break后面带标签,则跳到标签处

continue: 中止当前循环,进入下一循环

goto: 和break加标签用法一样

3. 值传递与引用传递

golang中的变量可以分为以下两种类型

  • 值类型:int、float、string、bool、array、struct
  • 引用类型: slice、pointer、map、chan 等
    值类型传递的是数值本身,被修改不会影响原来的值。
    引用类型传递的是内存地址,被修改时会影响原来的值。

4. 深拷贝和浅拷贝

浅拷贝复制过来的是内存地址,操作的是同一对象,但是深拷贝是新建一个对象,并且将源对象的内容通通复制一份。
使用深拷贝数据函数: copy(目标切片,数据源)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值