1、数组(array)

数组是具有相同数据类型的数据项组成的一组长度固定的序列,数据项叫做数组的元素,数组的长度必须是非负整数的常量,长度也是类型的一部分

1) 声明

数组声明需要指定组成元素的类型以及存储元素的数量(长度)。在数组声明后,其长度不可修改,数组的每个元素会根据对应类型的零值对进行初始化
image.png
image.png
%q 为每个字符串添加 ""
image.png
image.png

2) 字面量

a) 指定数组长度: [length]type{v1, v2, …, vlength}
b) 使用初始化元素数量推到数组长度: […]type{v1, v2, …, vlength}
c) 对指定位置元素进行初始化: [length]type{im:vm, …, sin:in}
image.png
image.png

3) 操作

a) 关系运算==、!=
image.png
b) 获取数组长度
使用 len 函数可获取数组的长度
image.png
c) 访问&修改
通过对编号对数组元素进行访问和修改,元素的编号从左到右依次为:0, 1, 2, …, n(n为数组长度-1)
image.png
image.png
d) 切片: array[start:end]/arraystart:end:cap获取数组的一部分元素做为切片
image.png
e) 遍历
可以通过 for+len+访问方式或 for-range 方式对数组中元素进行遍历
image.png
使用 for-range 遍历数组,range 返回两个元素分别为数组元素索引和值

4) 多维数组

数组的元素也可以是数组类型,此时称为多维数组
a) 声明&初始化
image.png
b) 访问&修改
image.png
c) 遍历
image.png

2、切片(slice)

切片是长度可变的数组(具有相同数据类型的数据项组成的一组长度可变的序列),切片由三部分组成:

  • 指针:指向切片第一个元素指向的数组元素的地址
  • 长度:切片元素的数量
  • 容量:切片开始到结束位置元素的数量

    1) 声明

    切片声明需要指定组成元素的类型,但不需要指定存储元素的数量(长度)。在切片声明后,会被初始化为 nil,表示暂不存在的切片
    image.png

    2) 初始化

    a) 使用字面量初始化:[]type{v1, v2, …, vn}
    b) 使用字面量初始化空切片: [``]type{}
    c) 指定长度和容量字面量初始化:[]type{im:vm, in:vn, ilength:vlength}
    d) 使用 make 函数初始化make([]type, len)/make([]type, len, cap),通过 make 函数创建长度为 len,容量为 cap 的切片,len 必须小于等于 cap
    e) 使用数组切片操作初始化:array[start:end]/array[start:end:cap](end<=cap<=len)
    image.png

    3) 操作

    a) 获取切片长度和容量
    使用 len 函数可获取切片的长度,使用 cap 函数可获取切片容量
    image.png
    b) 访问和修改
    通过对编号对切片元素进行访问和修改,元素的编号从左到右依次为:0, 1, 2, …, n(n为切片长度-1)
    image.png
    c) 切片: slice[start:end]用于创建一个新的切片,end <= src_cap
    image.png
    新创建切片长度和容量计算:len: end-start, cap: src_cap-start
    切片共享底层数组,若某个切片元素发生变化,则数组和其他有共享元素的切片也会发生变化
    image.png
    slice[start:end:cap]可用于限制新切片的容量值, end<=cap<= src_cap
    image.png
    新创建切片长度和容量计算:len: end-start, cap: cap-start
    d) 遍历
    可以通过 for+len+访问方式或 for-range 方式对切片中元素进行遍历
    image.png
    使用 for-range 遍历切片,range 返回两个元素分别为切片元素索引和值
    e) 增加元素
    使用 append 对切片增加一个或多个元素并返回修改后切片,当长度在容量范围内时只增加长度,容量和底层数组不变。当长度超过容量范围则会创建一个新的底层数组并对容量进行智能运算(元素数量<1024 时,约按原容量 1 倍增加,>1024 时约按原容量 0.25倍增加)
    image.png
    f) 复制切片到另一个切片
    复制元素数量为 src 元素数量和 dest 元素数量的最小值

    4) 使用

    a) 移除元素
    image.png
    b) 队列
    先进先出
    image.png
    c) 堆栈
    先进后出
    image.png

    5) 多维切片

    切片的元素也可以是切片类型,此时称为多维切片
    image.png

    6) 常用包

    sort 进行排序

    1. # 对切片数字进行排序
    2. func main() {
    3. xx:=[]int{1,42,53,56,5,12,6}
    4. sort.Ints(xx)
    5. fmt.Println(xx) // [1 5 6 12 42 53 56]
    6. }

    3、映射(map)

  • 映射是存储一系列无序的 key/value 对,通过 key 来对 value 进行操作(增、删、改、查)。映射的 key 只能为可使用==运算符的值类型(字符串、数字、布尔、数组),value 可以为任意类型 s

    1) 声明

  • map 声明需要指定组成元素 key 和 value 的类型,在声明后,会被初始化为 nil,表示暂不存在的映射

image.png

2) 初始化

a) 使用字面量初始化:map[type]type{k1:v1, k2:v2, …, kn:vn}
b) 使用字面量初始化空映射:map[type]type{ }
c) 使用 make 函数初始化,make(map[type]type),通过 make 函数创建映射
image.png

3) 操作

a) 获取元素的数量使用 len 函数获取映射元素的数量
image.png
b) 访问
image.png
当访问 key 存在与映射时则返回对应的值,否则返回值类型的零值
c) 判断 key 是否存在
通过 key访问元素时可接收两个值,第一个值为 value,第二个值为 bool类型表示元素是否存在,若存在为 true,否则为 false
image.png
d) 修改&增加
使用 key 对映射赋值时当 key 存在则修改 key 对应的 value,若 key 不存在则增加 key和 value
image.png
e) 删除
使用 delete 函数删除映射中已经存在的 key
image.png
f) 遍历
可通过 for-range 对映射中个元素进行遍历,range 返回两个元素分别为映射的 key 和value
image.png

func main() {
    scores :=map[int]string{1: "大冬",2:"xxd",3:"西索"}
    fmt.Println(scores[1]) //大冬
    // 增
    scores[4]="小D"
    fmt.Println(scores) //map[1:大冬 2:xxd 3:西索 4:小D]
    // 删
    delete(scores,4)
    fmt.Println(scores) //map[1:大冬 2:xxd 3:西索]
    // 改
    scores[2]="小弟"
    fmt.Println(scores) //map[1:大冬 2:小弟 3:西索]
    //查
    if v,ok:= scores[1]; ok{
        fmt.Println(v)            //大冬
    }
    // 遍历
    for k,v:=range scores{
        fmt.Println(k,v)
    }
}

e) 多维映射
image.png
image.png

4) 使用

  • 统计每个切片字符串出现的次数

image.png

func main() {
    nums := []string{"xxd", "dd", "zz", "aa", "xxd", "xxd", "zz", "xxd", "dd"}
    users := map[string]int{}
    for _, v := range nums {
        users[v]++
    }
    fmt.Println(users)
}

image.png

  • 统计演讲稿中一段话中所有英文字母出现的次数 ``go func main() { nums :=Youth means a temperamental predominance of courage over timidity, of the appetite for adventure over the love of ease. This often exits in a man of 60, more than a boy of 20.nobody grows merely by the number of years; we grow old by deserting our ideas. Years may wrinkle the skin, but to give up enthusiasm wrinkles the soul. Worry, fear, self-distrust1 bows the heart and turns the spirit back to dust. ` user := map[rune]int{} for _, v := range nums {
      if v >= 'A' && v <= 'Z' || v >= 'a' && v <= 'z' {
          user[v]++
      }
    
    } fmt.Println(user) for k, v := range user {
      fmt.Printf("%c:%v\t", k, v)
    
    } }

[root@i-vzozw11z test]# go run main.go map[84:1 87:1 89:2 97:22 98:8 99:3 100:10 101:42 102:10 103:5 104:12 105:18 107:4 108:8 109:11 110:18 111:27 112:6 114:25 115:21 116:29 117:12 118:5 119:6 120:1 121:9] g:5 x:1 w:6 u:12 m:11 s:21 c:3 y:9 h:12 n:18 l:8 f:10 d:10 T:1 b:8 W:1 e:42 a:22 p:6 r:25 v:5 k:4 Y:2 o:27 t:29 i:18

<a name="smQQ6"></a>
# 4、字符串/字节切片
<a name="jyBU7"></a>
## 1)区别/转换

- 区别
   - Bytes:将Buffer对象转化为字节切片
   - String:将Buffer对象转换为字符串
- 转换
   - 可以将String通过函数byte[]转化为字节切片,同时可通过byte[]转化为string
```go
func main() {
    var bytes []byte= []byte{'a','b','c'}
    fmt.Printf("%T,%#v\n",bytes,bytes)

    s:=string(bytes)
    fmt.Println(s)

    b:=[]byte(s)
    fmt.Printf("%T,%#v",b,b)
}

输出:
[]uint8,[]byte{0x61, 0x62, 0x63}
abc
[]uint8,[]byte{0x61, 0x62, 0x63}

2)常用模块strings

func main() {
    // 比较
    fmt.Println(strings.Compare("a", "b"))
    fmt.Println(strings.Compare("a", "a"))
    fmt.Println(strings.Compare("b", "a"))

    // 包含
    fmt.Println(strings.Contains("我是kk", "kk"))
    fmt.Println(strings.Contains("我是kk", "kk1"))

    fmt.Println(strings.ContainsAny("我是kk", "kk1"))
    fmt.Println(strings.ContainsAny("我是kk", "123"))

    fmt.Println(strings.ContainsRune("我是kk", '我'))
    fmt.Println(strings.ContainsRune("我是kk", 'a'))

    // 计算次数
    fmt.Println(strings.Count("我是kk", "kk"))
    fmt.Println(strings.Count("我是kk", "k"))
    fmt.Println(strings.Count("我是kk", "a"))

    // 比较
    fmt.Println(strings.EqualFold("abc", "ABC"))
    fmt.Println(strings.EqualFold("abc", "abc"))
    fmt.Println(strings.EqualFold("abc", "xyz"))

    // 空白符
    // 空格 tab 回车 换行 换页 ...
    fmt.Printf("%#v\n", strings.Fields("aafds b\tc\nd\re\ff"))

    // 开头*结尾
    fmt.Println(strings.HasPrefix("abc", "ab"))
    fmt.Println(strings.HasPrefix("abc", "bc"))

    fmt.Println(strings.HasSuffix("abc", "bc"))
    fmt.Println(strings.HasSuffix("abc", "ab"))

    // 字符串出现位置
    fmt.Println(strings.Index("abcdefdef", "def"))
    fmt.Println(strings.Index("abcdefdef", "xxx"))
    fmt.Println(strings.LastIndex("abcdefdef", "def"))
    fmt.Println(strings.LastIndex("abcdefdef", "xxx"))

    // 连接 分割
    fmt.Println(strings.Join([]string{"ab", "cd", "ef"}, "-"))

    fmt.Printf("%#v\n", strings.Split("ab-ab-ab", "-"))
    fmt.Printf("%#v\n", strings.SplitN("ab-ab-ab", "-", 2))

    // 重复

    fmt.Println(strings.Repeat("*", 5))

    // 替换
    fmt.Println(strings.Replace("xyzxyzxxxxyz", "yz", "mn", -1))
    fmt.Println(strings.Replace("xyzxyzxxxxyz", "yz", "mn", 1))
    fmt.Println(strings.ReplaceAll("xyzxyzxxxxyz", "yz", "mn"))

    // 首字母大写
    fmt.Println(strings.Title("my name is kk"))

    fmt.Println(strings.ToLower("abcABC"))
    fmt.Println(strings.ToUpper("abcABC"))

    // trim
    fmt.Println(strings.Trim("abcdefabc", "bc"))
    fmt.Println(strings.Trim("abcdefabc", "abc"))
    fmt.Println(strings.TrimSpace(" \n\f\tabcdefabc\t"))
    fmt.Println(strings.TrimLeft("cabcdefabca", "abc")) // 左边字符出现在子字符串中则替换
    fmt.Println(strings.TrimRight("cabcdefabca", "abc"))

    fmt.Println(strings.TrimPrefix("abccabcdefabca", "abc")) // 字符串当成一个整体替换
    fmt.Println(strings.TrimSuffix("cabcdefabca", "abc"))
}
  • 统计中文字符串的包utf8.RuneCountInString ```go func main() { s:=”大叔大婶大所多无的晚上” fmt.Println(utf8.RuneCountInString(s)) }

输出: 11

<a name="grTqz"></a>
## 3)字符串类型转换

- 字符串转换其他类型
```go
func main() {
    // 字符串转换bool类型
    if v,err:=strconv.ParseBool("true");err==nil{
        fmt.Printf("%T,%v\n",v,v)
    }else {
        fmt.Println(err)
    }

    // 字符串转换int类型
    if v,err:=strconv.Atoi("1990");err==nil{
        fmt.Printf("%T,%v\n",v,v)
    }else {
        fmt.Println(err)
    }

    // 字符串转换float类型
    if v,err:=strconv.ParseFloat("1.1",64);err==nil{
        fmt.Printf("%T,%v\n",v,v)
    }else {
        fmt.Println(err)
    }
}

输出:
bool,true
int,1990
float64,1.1
  • 其他类型转换成字符串 ```go func main() { // int 转换成字符串 sd:=fmt.Sprintf(“%d”,12) fmt.Printf(“%T,%s\n”,sd,sd)

    // float64 转换成字符串 sf:=fmt.Sprintf(“%.2f”,12.1) fmt.Printf(“%T,%s\n”,sf,sf)

    fmt.Printf(“%T,%q\n”,strconv.FormatBool(false),strconv.FormatBool(false)) fmt.Printf(“%T,%q\n”,strconv.Itoa(120),strconv.Itoa(120)) fmt.Printf(“%T,%q\n”,strconv.FormatInt(99,10),strconv.FormatInt(99,10)) fmt.Printf(“%T,%q\n”,strconv.FormatFloat(10.1,’E’,-1,64),strconv.FormatFloat(10.1,’E’,-1,64)) }

输出: string,12 string,12.10 string,”false” string,”120” string,”99” string,”1.01E+01”

<a name="JHJHw"></a>
# 5、作业

- 获取切片数组中最大和第二大的数
```go
func main() {
    s := []int{1, 5, 117, 3, 77, 32, 54, 6}
    for i := 0; i < len(s)-1; i++ {
        for j := 0; j < len(s)-1; j++ {
            if s[j] > s[j+1] {
                s[j], s[j+1] = s[j+1], s[j]
            }
        }
    }
    fmt.Println(s[len(s)-1])    // 第一大的数
    fmt.Println(s[len(s)-2])    // 第二大的数
}
  • 获取映射中所有的key,value的值组成切片
    func main() {
      s:=map[string]int{"大冬":1,"xxd":2,"ceshi":3}
      test1:=make([]string,len(s))
      var test2 []int
      i:=0
      for k,v:=range s{
          test1[i]=k
          i++
          test2=append(test2,v)
      }
      fmt.Println(test1)
      fmt.Println(test2)
    }