文章目录

  • 1.什么是指针
  • 2.容器
    • 2.1 数组——固定大小的连续空间
    • 2.2 切片(slice)——动态分配大小的连续空间
      • 2.2.1 从指定范围中生成切片
      • 2.2.2 表示原有的切片
      • 2.2.3 重置切片,清空拥有的元素
      • 2.2.4 声明切片
      • 2.2.5 使用make()函数构造切片
      • 2.2.6 使用append()函数为切片添加元素
      • 2.2.7 复制切片元素到另一个切片
      • 2.2.8 从切片中删除元素
  • 3. 映射(map)
      • 能够在并发环境中使用的map——sync.Map
  • 4. 列表(list)

1.什么是指针

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用“&”操作符放在变量前面对变量进行“取地址”操作。
首先来看一下基本语法

1
2
3
4
5
6
func main() {
    i := 1
    str := "123"
    var ptr *int = &i
    fmt.Println(i, ptr, &i, str, &str)
}

在这里插入图片描述
在这里插入图片描述
输出值在每次运行是不同的,代表cat和str两个变量在运行时的地址。在32位平台上,将是32位地址;64位平台上是64位地址。

每个变量都拥有地址,指针的值就是地址。
再来几个例子:
首先我们得晓得一下:
fmt.Printf的一些参数
在这里插入图片描述

取指针内的值:

1
fmt.Println(*ptr)

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
func main() {
    i := 1
    str := "123"
    ptr := &str//声明指向int的指针
    fmt.Println(i, ptr, &i, str, &str)
    fmt.Println(*ptr)
    fmt.Printf("%t\n",ptr)
    fmt.Printf("%T\n",ptr)
    fmt.Printf("%T\n",*ptr)
}

在这里插入图片描述
创建指针的另一种方法——new()函数
new()函数可以创建一个对应类型的指针,创建过程会分配内存。被创建的指针指向的值为默认值。

1
2
3
4
    prtstring := new(string)
    *prtstring="laji"
    fmt.Printf("%T",prtstring)
    fmt.Printf(*prtstring)

在这里插入图片描述

2.容器

2.1 数组——固定大小的连续空间

声明数组
在这里插入图片描述
初始化数组
数组可以在声明时使用初始化列表进行元素设置

1
var array = [3]string{"hhhh", "oooo", "kkkk"}

也可以使用,“…”表示让编译器确定数组大小。

1
var array1 = [...]string{"111"}

数组遍历:

1
2
3
for k, v := range array{
        fmt.Println(k, v)
    }

Go的数组是值类型,数组间不会互相影响

1
2
3
4
5
6
7
8
fmt.Println(&array[0])
    test(array)


----------------------
func test(ints [3]string) {
    fmt.Println(&ints[0])
}

在这里插入图片描述
地址不同了

2.2 切片(slice)——动态分配大小的连续空间

在这里插入图片描述
切片是引用类型
切片默认指向一段连续内存区域,可以是数组,也可以是切片本身。
从连续内存区域生成切片是常见的操作,语法如下:
slice [开始位置:结束位置]

1
2
3
● slice表示目标切片对象。
● 开始位置对应目标切片对象的索引。
● 结束位置对应目标切片的结束索引。

从数组或切片生成新的切片拥有如下特性:
● 取出的元素数量为:结束位置-开始位置。
● 取出元素不包含结束位置对应的索引,切片最后一个元素使用slice[len(slice)]获取。
● 当缺省开始位置时,表示从连续区域开头到结束位置。
● 当缺省结束位置时,表示从开始位置到整个连续区域末尾。
● 两者同时缺省时,与切片本身等效。
● 两者同时为0时,等效于空切片,一般用于切片复位。
● 根据索引位置取切片slice元素值时,取值范围是(0~len(slice)-1),超界会报运行时错误。生成切片时,结束位置可以填写len(slice)但不会报错。

2.2.1 从指定范围中生成切片

切片和数组密不可分。
如果将数组理解为一栋办公楼,那么切片就是把不同的连续楼层出租给使用者。出租的过程需要选择开始楼层和结束楼层,这个过程就会生成切片。
含义就是:

1
2
3
4
    var slice = [3]int{1, 2, 3}
    ints := slice[0:2] // 1 2
    ints[0]=2 // 修改 1 为2
    fmt.Println(slice) //查看原数组是否被修改

在这里插入图片描述

2.2.2 表示原有的切片

slice[:] 表示得到和原数组大小一致的切片

2.2.3 重置切片,清空拥有的元素

slice[0:0] 切片大小变成空

1
2
i := slice[0:0]
    fmt.Println(i)

结果为:

1
[]

2.2.4 声明切片

每一种类型都可以拥有其切片类型,表示多个类型元素的连续集合。因此切片类型也可以被声明。

1
var name []int

2.2.5 使用make()函数构造切片

1
2
3
4
    var name []int
    name = make([]int, 3, 5)
    i2 := make([]int, 2, 8)
    fmt.Println(name,len(name),i2,len(i2))

在这里插入图片描述
i2均是预分配2个元素的切片,只是i2的内部存储空间已经分配了8个,但实际使用了2个元素。

2.2.6 使用append()函数为切片添加元素

Go语言的内建函数append()可以为切片动态添加元素。每个切片会指向一片内存空间,这片空间能容纳一定数量的元素。当空间不能容纳足够多的元素时,切片就会进行“扩容”。“扩容”操作往往发生在append()函数调用时。

1
2
3
4
5
    var name []int
    name= append(name, 1)
    fmt.Println(name,len(name),cap(name))
    name= append(name, 2)
    fmt.Println(name,len(name), cap(name))

在这里插入图片描述
切片在扩容时,容量的扩展规律按容量的2倍数扩充,例如1、2、4、8、16……

1
2
3
4
5
var nums []int
    for i:=0;i<10;i++{
        nums= append(nums, i)
        fmt.Printf("len:%d,cap:%d,pointer:%p\n",len(nums),cap(nums),nums)
    }

在这里插入图片描述

2.2.7 复制切片元素到另一个切片

使用Go语言内建的copy()函数,可以迅速地将一个切片的数据复制到另外一个切片空间中,copy()函数的使用格式如下

1
2
3
4
5
6
7
8
9
10
11
12
src := make([]int, 4, 8)
    fmt.Printf("len:%d,cap:%d,pointer:%p\n,srcvalue:%v\n", len(src), cap(src), src, src)
    dest := make([]int, 2, 10)
    fmt.Printf("len:%d,cap:%d,pointer:%p\n,destvalue:%v\n", len(dest), cap(dest), dest, dest)
    src[0] = 1
    fmt.Printf("len:%d,cap:%d,pointer:%p\n,destvalue:%v\n", len(dest), cap(dest), dest, dest)
    src[3] = 5
    copy(dest, src)
    fmt.Printf("len:%d,cap:%d,pointer:%p,destvalue:%v\n", len(dest), cap(dest), dest, dest)
    dest[0]=1213
    fmt.Printf("len:%d,cap:%d,pointer:%p,destvalue:%v\n", len(dest), cap(dest), dest, dest)
    fmt.Printf("len:%d,cap:%d,pointer:%p\n,srcvalue:%v\n", len(src), cap(src), src, src)

在这里插入图片描述

2.2.8 从切片中删除元素

Go语言并没有对删除切片元素提供专用的语法或者接口,需要使用切片本身的特性来删除元素。

1
    customer = append(customer[:index], customer[index+1:]...)

在这里插入图片描述
删除过程。

连续容器的元素删除无论是在任何语言中,都要将删除点前后的元素移动到新的位置。随着元素的增加,这个过程将会变得极为耗时。因此,当业务需要大量、频繁地从一个切片中删除元素时,如果对性能要求较高,就需要反思是否需要更换其他的容器(如双链表等能快速从删除点删除元素)。

3. 映射(map)

Go语言提供的映射关系容器为map。map使用散列表(hash)实现。

1
2
3
4
    mmap := make(map[string]int)
    mmap["okok"]=16
    fmt.Println(mmap["okok"])
    fmt.Println(mmap["ok2ok"])

在这里插入图片描述
填充式创建:
在这里插入图片描述

遍历map的“键值对”——访问每一个map中的关联关系

1
2
3
4
5
6
7
8
9
    for k, v := range mmap {
        fmt.Println(k, v)
    }
    for _, v := range mmap {
        fmt.Println( v)
    }
    for k:= range mmap {
        fmt.Println(k)
    }

在这里插入图片描述

使用delete()函数从map中删除键值对
在这里插入图片描述

清空map中的所有元素
Go语言中并没有为map提供任何清空所有元素的函数、方法。清空map的唯一办法就是重新make一个新的map。不用担心垃圾回收的效率,Go语言中的并行垃圾回收效率比写一个清空函数高效多了。

能够在并发环境中使用的map——sync.Map

sync.Map有以下特性:
● 无须初始化,直接声明即可。
● sync.Map不能使用map的方式进行取值和设置等操作,而是使用sync.Map的方法进行调用。Store表示存储,Load表示获取,Delete表示删除。
● 使用Range配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值。Range参数中的回调函数的返回值功能是:需要继续迭代遍历时,返回true;终止迭代遍历时,返回false。

4. 列表(list)

列表是一种非连续存储的容器,由多个节点组成,节点通过一些变量记录彼此之间的关系。列表有多种实现方法,如单链表、双链表等。

初始化列表
1.通过container/list包的New方法初始化list

1
l := list.New()

2.通过声明初始化list

1
    l2 := list.List{}

双链表支持从队列前方或后方插入元素,分别对应的方法是Push Front和Push Back。
举例:

1
2
3
4
5
    l := list.New()
    l.PushBack("fiest")          //增加尾部
    front := l.PushFront("dddd") // 增加头部
    l.InsertAfter("aaaa", front)
    l.Remove(front)

在这里插入图片描述

遍历列表——访问列表的每一个元素
在这里插入图片描述