「Golang成长之路」内建容器

Golang
314
0
0
2022-04-19
标签   Golang进阶

一、数组(Array)

数组:数组是指有序的元素序列。如果将有限个类型相同的变量的集合命名,那么这个名称就是数组名,而组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量,而数组中的数据可以使用下标(索引)来查找到。

其实在编程语言中数组的概念是一样的,下面具体来看看golang中数组是如何定义和使用的:

1.数组的定义

  • 方法一:
var arr1 [5]int   //定义一个拥有5个元素的数组,此时元素全为0
  • 方法二:
arr2 := [5]int{0, 1, 2, 3, 4}     //定义并放入值
  • 方法三:
arr3 := [...]int{0, 1, 2, 3, 4} //用[...],此时不需写入数组空间具体是多少
  • 二维数组的定义:
package main
import "mft"
func main {
//二维数组
var arr4 [4][5]int
fmt.Println(arr4)
}
  • 输出为:
[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

2.数组的使用

  • 遍历
package main
import "fmt"
arr :=[...]int{0, 1, 2, 3, 4}
for i := range arr{
  fmt.Println(arr[i])
}
  • 输出为:
0
1
2
3
4
  • 也可以这样遍历:
//.数组的遍历
for i,v :=  range arr3{   //i为对应元素的索引值,v为元素值
     fmt.Println(i, v)
}
  • 输出为:

0 0

1 1

2 2

3 3

4 4

  1. 改变元素的值
arr :=[...]int{0, 1, 2, 3, 4}
arr[0] = 100  //将arr[0]改为100
fmt.Println(arr)
arr[0] = 0  //将arr[0]改回0
fmt.Println(arr)
  1. 输出为:
[100 1 2 3 4 ]
[0 1 2 3 4 ]
  • 数组的值传递
  • 数组的值传递仍然是将整个数组copy一份传入函数,不会改变arr的值
//数组的值传递
package main
import "fmt"
//定义函数:
func printarr1(arr [5]int){
  arr[0] = 100
  fmt.Println(arr)
}
func main(){printarr1(arr)
  fmt.Println(arr)
}
  • 输出为:
[0 1 2 3 4 ]
  • 使用指针
  • 使用指针是将数组的相应值的地址传入函数
//使用指针
package main
import "fmt"
//定义函数:
func printarr2(arr *[5]int) {
  arr[0] = 100
  fmt.Println(arr)
}
func main(){printarr2(&arr3)
  fmt.Println(arr3)
}
  • 输出为:
[100 1 2 3 4]

二、切片(Slice)

切片是golang中重要操作之一

直接看操作:

package main
import main
func main(){
    //切片
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    s := arr[2:6]
    fmt.Println("s = ",s)
    fmt.Println("arr[2:6 =",arr[2:6])
    fmt.Println("arr[:6] = ",arr[:6])
    fmt.Println("arr[2:] = ",arr[2:])
    fmt.Println("arr[:] = ",arr[:])
}

输出为:

s =  [2 3 4 5]
arr[2:6 = [2 3 4 5]
arr[:6] =  [0 1 2 3 4 5]
arr[2:] =  [2 3 4 5 6 7]
arr[:] =  [0 1 2 3 4 5 6 7]
  1. Slice值的改变
  2. 改变Slice中元素的值,会导致底层arr值的改变
package main
import m="fmt"
//定义函数,改变Slice的值
//切片
func updateSlice(s []int){
   s[0] = 100
}
//主函数
func main(){
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    s1 :=arr[2:]
    s2 := arr[:]
    //改变之前
    fmt.Println(s1)
    fmt.Println(s2)
    fmt.Println("change after:")
    //函数调用
    updateSlice(s1)
    fmt.Println(s1)
    //最后底层的arr的值也会随之改变
    fmt.Println(arr)
}
  1. 输出为:
[2 3 4 5 6 7]
[0 1 2 3 4 5 6 7]
change after:
[100 3 4 5 6 7]
[0 1 100 3 4 5 6 7]
  1. 现在我们再来改变S2:
fmt.Println(s2)
updateSlice(s2)
fmt.Println(s2)
fmt.Print(arr)
  1. 输出为:
[0 1 100 3 4 5 6 7]
[100 1 100 3 4 5 6 7]
[100 1 100 3 4 5 6 7]

这里还有一种情况:Slice的更新

package main
import "fmt"

func main(){
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    s2 := arr[:]
    //Slice中值的更新 
    //对Slice的操作,其实是对底层arr的修改
    fmt.Println(s2)
    s2 = s2[:5]
    fmt.Println(s2)
    s2 = s2[2:]
    fmt.Println(s2)
    fmt.Println(arr)
}

输出为:

[0 1 2 3 4 5 6 7]
[0 1 2 3 4]
[2 3 4]
[0 1 2 3 4 5 6 7]
  1. Slice的扩展
  2. 先来看一个例子:
//Slice的扩展
package main
import "fmt"
func main(){
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    fmt.Println("Extneding Slice:")
    fmt.Println(arr)
    s1 = arr[2:6]
    s2 = s1[3:5]
    fmt.Println(s1)
    fmt.Println(s2)
    fmt.Println(arr)
}
  1. 现在肯定对这段代码有疑问吧!
  2. s2 = s1[3:5] 会不会报错?
  3. 答案:不会!
  4. 下面来看看运行结果:
[0 1 2 3 4 5 6 7]
[2 3 4 5]
[5 6]
[0 1 2 3 4 5 6 7]

*原因:在golang中Slice是可是往后扩展的,例如上面

arr := […]int{0, 1, 2, 3, 4, 5, 6, 7}

s1 = arr[2:6] = [2 3 4 5]

s2 = s1[3:5],此时已经超出s1的范围了,但是Slice是对底层arr的操作,并且可以往后扩展的,所以往底层走就应该是[5 6],s2 = s1[3:5] = [5 6] *

  1. 向slice添加元素
  2. 向slice添加元素使用append(s, x)
//向slice添加元素
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
//切分
s1 :=arr[2:]
s2 := arr[:]
//打印
fmt.Println(s1)
fmt.Println(s2)
//添加元素
s3 := append(s2, 10)
s4 := append(s3, 11)
s5 := append(s4, 12)
fmt.Println("s3, s4, s5 =",s3, s4, s5)
fmt.Println("arr = ",arr)
  1. 输出为:
[2 3 4 5 6 7]
[0 1 2 3 4 5 6 7]
s3, s4, s5 = [0 1 2 3 4 5 6 7 10] [0 1 2 3 4 5 6 7 10 11] [0 1 2 3 4 5 6 7 10 11 12]
arr =  [0 1 2 3 4 5 6 7]  //arr的容量已经固定,不会变
  1. slice的建立
  • 1
package mian
import "fmt"
//定义函数
func printslice(s []int){
 fmt.Printf(" s=%v, len=%d, cap=%d",s, len(s), cap(s))
}
func main(){
    var s []int 
    //s的初始化,生成100个奇数 
    for i:=0; i < 100; i++{printslice(s)
       fmt.Print("\n")
       s = append(s, 2*i + 1)
    }
}
  • 2
package main
import "fmt"
//定义函数
func printslice(s []int){
    fmt.Printf(" s=%v, len=%d, cap=%d",s, len(s), cap(s))
}
func main(){
    //graet slice
    s1 := []int{0,1,2}
    s2 := make([]int, 16)
    s3 := make([]int, 10, 32)
    //调用函数
    printslice(s1)
    printslice(s2)
    printslice(s3)
}
  • 输出为:
s=[0 1 2], len=3, cap=3
s=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap=16
s=[0 0 0 0 0 0 0 0 0 0], len=10, cap=32
  1. copy Slice
//copy slice
copy(s2, s1)   //将s1的内容copy到s2上
fmt.Println(s2)
  1. delete Slice
  2. 删除操作
package main
import "fmt"
定义函数
func printslice(s []int){
    fmt.Printf(" s=%v, len=%d, cap=%d",s, len(s), cap(s))
}
//主函数
func main(){
    //delete "2"
    s5 := []int{0, 1, 2, 3, 4, 5, 6, 7}
    s5 = append(s5[:2], s5[3:]...)  //使用切片(Slice)
    printslice(s5)
    //delete front
    s5 = s5[1:]
    printslice(s5)
    //delete tail
    s5 = s5[:len(s5)-1]
    printslice(s5)
}
  1. 输出为:
s=[0 1 3 4 5 6 7], len=7, cap=8
s=[1 3 4 5 6 7], len=6, cap=7
s=[1 3 4 5 6], len=5, cap=7

三、映射(Map)

map:是一个无序,key—value对,不会出现某个key对应不同的value

  • map的定义:
//定义map
m :=  map[string]string{      //[string]对应key,string对应value"name":"yangkuang", 
    "work":"students",
    "year": "20",
}
m3 := map[string]int{"a": 0,
"b": 1,
"c": 2,

//空map的定义
m1 := make(map[string]int)   // empty map1
var m2 map[string]int
fmt.Println(m, m1, m2)    //map2 == nil
  • 输出为:
map[name:yangkuang work:students year:21] map[] map[]
  • map的遍历
   for k, v := range m3{
       fmt.Println(k, v)}
  • 输出为:
a 0
b 1
c 2
  • map的查找
func main(){
    //定义map
    m :=  map[string]string{"name":"yangkuang",
        "work":"students",
       "year": "21",
    }
    iname, ok := m["name"]   //key—name存在则将key对应的value赋值给iname,并且将ok赋值为true,否则ok为false
    fmt.Println(iname,ok)   //输出:yangkuang true
}