Skip to content

内建容器

数组

  • 数量写在类型前面
  • 遍历数组 range
  • 数组是值类型

    • [10]int[20]int 是不同类型
    • 调用 func f(arr [10]int)拷贝 数组
    package main
    
    import "fmt"
    
    func main() {
        var arr1 [5]int
        arr2 := [3]int{1, 2, 3}
        arr3 := [...]int{2, 4, 6, 8, 10}
    
        // 二维数组,四行五列
        var grid [4][5]int
    
        fmt.Println(arr1, arr2, arr3)
    
        // 遍历数组
        for i, v := range arr3 {
            fmt.Println(i, v)
        }
    }
    
    
    /*
    [0 0 0 0 0] [1 2 3] [2 4 6 8 10] [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
    0 2
    1 4
    2 6
    3 8
    4 10
    */
    

切片的概念

  • Slice本身没有数据,是对底层array的一个view

    1
    2
    3
    4
    5
    6
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    s := arr[2:6]
    s[0] = 10
    
    
    // arr 的值变为 [0 1 10 3, 4, 5, 6, 7]
    

  • Slice的扩展

    Slice的扩展
    1
    2
    3
    4
    5
    6
    7
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    s1 := arr[2:6]
    s2 := s1[3:5]
    
    
    // s的值为[2 3 4 5], s2的值为[5 6]
    // slice可以向后扩展,不可以向前扩展
    

  • Slice的实现

    Slice的扩展

  • 范例

    package main
    
    import "fmt"
    
    func main() {
        arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
        fmt.Println("arr[2:6] = ", arr[2:6])
        fmt.Println("arr[:6] = ", arr[:6])
        fmt.Println("arr[2:] = ", arr[2:])
        fmt.Println("arr[:] = ", arr[:])
    
        s1 := arr[2:]
        fmt.Println("s1 = ", s1)
        s2 := arr[:]
        fmt.Println("s2 = ", s2)
        updateSlice(s1)
        fmt.Println("s1 update res means", s1)
        fmt.Println("arr update res means", arr)
    
        fmt.Println("Extending slice")
        arr[0], arr[2] = 0, 2
        s1 = arr[2:6]
        s2 = s1[3:5]
        fmt.Printf("s1=%v, len(s1)=%d, cap(s1)=%d\n", s1, len(s1), cap(s1))
        fmt.Printf("s2=%v, len(s2)=%d, cap(s2)=%d\n", s2, len(s2), cap(s2))
    }
    
    
    /*
    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]
    s1 =  [2 3 4 5 6 7]
    s2 =  [0 1 2 3 4 5 6 7]
    s1 update res means [1000 3 4 5 6 7]
    arr update res means [0 1 1000 3 4 5 6 7]
    Extending slice
    s1=[2 3 4 5], len(s1)=4, cap(s1)=6
    s2=[5 6], len(s2)=2, cap(s2)=3
    */
    

切片的操作

  • 向Slice添加元素

    • 添加元素时如果超越cap,系统会重新分配更大的底层数组
    • 由于值传递的关系,必须接受append的返回值
    • s = append(s, val)

      arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
      s1 := arr[2:6]
      s2 := s1[3:5]
      s3 := append(s2, 10)
      s4 := append(s3, 11)
      s5 := append(s4, 12)
      
      fmt.Println("s3, s4, s5 = ", s3, s4, s5)
      fmt.Println("arr = ", arr)
      
      
      /*
      s3, s4, s5 =  [5 6 10] [5 6 10 11] [5 6 10 11 12]
      arr =  [0 1 2 3 4 5 6 10]
      */
      
  • 更多操作

    package main
    
    import "fmt"
    
    func printSlice(s []int) {
        fmt.Printf("%v, len = %d, cap = %d\n", s, len(s), cap(s))
    }
    
    func main() {
        // Create Slice
        fmt.Println("Create Slice")
        var s []int // zero value for slice is nil
        for i := 0; i < 20; i++ {
            printSlice(s)
            s = append(s, 2*i+1)
        }
        fmt.Println(s)
    
        // 创建数组的方法
        s1 := []int{2, 4, 6, 8}
        printSlice(s1)
        s2 := make([]int, 16)
        s3 := make([]int, 10, 32)
        printSlice(s2)
        printSlice(s3)
    
        // Copying slice
        fmt.Println("Copying slice")
        copy(s2, s1)
        fmt.Println(s2)
    
        // Deleting ele from slice
        fmt.Println("Deleting slice")
        // 删除s2下标为3的
        fmt.Println("删除s2下标为3的")
        s2 = append(s2[:3], s2[4:]...)
        printSlice(s2)
    
        fmt.Println("Popping from front")
        front := s2[0]
        s2 = s2[1:]
    
        fmt.Println("Popping from back")
        tail := s2[len(s2)-1]
        s2 = s2[:len(s2)-1]
        fmt.Println("front=", front, "tail=", tail)
        printSlice(s2)
    }
    
    
    
    /*
    Create Slice
    [], len = 0, cap = 0
    [1], len = 1, cap = 1
    [1 3], len = 2, cap = 2
    [1 3 5], len = 3, cap = 4
    [1 3 5 7], len = 4, cap = 4
    [1 3 5 7 9], len = 5, cap = 8
    [1 3 5 7 9 11], len = 6, cap = 8
    [1 3 5 7 9 11 13], len = 7, cap = 8
    [1 3 5 7 9 11 13 15], len = 8, cap = 8
    [1 3 5 7 9 11 13 15 17], len = 9, cap = 16
    [1 3 5 7 9 11 13 15 17 19], len = 10, cap = 16
    [1 3 5 7 9 11 13 15 17 19 21], len = 11, cap = 16
    [1 3 5 7 9 11 13 15 17 19 21 23], len = 12, cap = 16
    [1 3 5 7 9 11 13 15 17 19 21 23 25], len = 13, cap = 16
    [1 3 5 7 9 11 13 15 17 19 21 23 25 27], len = 14, cap = 16
    [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29], len = 15, cap = 16
    [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31], len = 16, cap = 16
    [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33], len = 17, cap = 32
    [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35], len = 18, cap = 32
    [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37], len = 19, cap = 32
    [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39]
    [2 4 6 8], len = 4, cap = 4
    [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len = 16, cap = 16
    [0 0 0 0 0 0 0 0 0 0], len = 10, cap = 32
    Copying slice
    [2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0]
    Deleting slice
    删除s2下标为3的
    [2 4 6 0 0 0 0 0 0 0 0 0 0 0 0], len = 15, cap = 16
    Popping from front
    Popping from back
    front= 2 tail= 0
    [4 6 0 0 0 0 0 0 0 0 0 0 0], len = 13, cap = 15
    */
    

Map

  • map[K]V
  • map[K1]map[K2]V (复合map)
  • 创建:make(map[string]int)
  • 获取元素:m[key]
  • key不存在时,获得value类型的初始值
  • 用value, ok := m[key] 来判断是否存在key
  • 用delete删除一个key
  • 使用range遍历key,或者遍历key, value对
    • 不保证遍历顺序,如需要顺序,需要手动对key进行排序操作
  • 使用len获得元素的个数
  • map使用哈希表,必须可以比较相等
  • 除了slice、map、function的内建类型都可以作为key
  • Struct类型不包含上述字段,也可作为key
  • 范例
    package main
    
    import "fmt"
    
    func main() {
        // 创建map
        m := map[string]string{
            "name": "cc",
            "old":  "18",
            "sex":  "male",
        }
    
        // 使用make创建空map
        m2 := make(map[string]int) // m2 == empty map
    
        // 使用var创建空map
        var m3 map[string]int // m3 == nil
    
        fmt.Println(m, m2, m3)
    
        // 遍历map
        for k, v := range m {
            fmt.Println(k, v)
        }
    
        // 操作map
        fmt.Println("操作map")
        sex, ok := m["sex"]
        fmt.Println("sex means:", sex, "isset:", ok)
        // key不存在时的判断依据 ok
        se, ok := m["se"]
        fmt.Println("sex means:", se, "isset:", ok)
        // 优化写法
        if se, ok := m["se"]; ok {
            fmt.Println(se)
        } else {
            fmt.Println("key does not exist.")
        }
    
        // 删除map
        fmt.Println("删除map")
        name, ok := m["name"]
        fmt.Println(name, ok)
    
        delete(m, "name")
        name, ok = m["name"]
        fmt.Println(name, ok)
    }
    
    
    /*
    map[name:cc old:18 sex:male] map[] map[]
    name cc
    old 18
    sex male
    操作map
    sex means: male isset: true
    sex means:  isset: false
    key does not exist.
    删除map
    cc true
    false
    */
    

Map例题

寻找最长不含有重复字符的子串
例如:
   qweqwert -> qwe
   cdewqcfewq -> cdewqcf
   ccccccc -> c

实现逻辑:对于每一个字母x
     lastOccurred[x]不存在,或者 < start -> 无需操作
     lastOccurred[x] >= start -> 更新start
     更新lastOccurred[x],更新maxLength

package main

import "fmt"

func execStringSubStr(s string) int {
    last := make(map[byte]int)
    start := 0
    maxLength := 0
    for i, ch := range []byte(s) {
        if lastI, ok := last[ch]; ok && lastI >= start {
            start = lastI + 1
        }
        if i-start+1 > maxLength {
            maxLength = i - start + 1
        }
        last[ch] = i
    }
    return maxLength
}

func main() {
    fmt.Println(execStringSubStr("abcabcbb"))
}

字符和字符串

  • Fields:字段将字符串 s 拆分为一个或多个连续空白字符的每个实例,如 unicode IsSpace 定义的那样,如果 s 仅包含空白,则返回 s 的子字符串切片或空切片。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        fmt.Printf("Fields are: %q", strings.Fields("  foo bar  baz   "))
    }
    
    
    // Fields are: ["foo" "bar" "baz"]
    
  • Split
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        fmt.Printf("%q\n", strings.Split("a,b,c", ","))
        fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))
        fmt.Printf("%q\n", strings.Split(" xyz ", ""))
        fmt.Printf("%q\n", strings.Split("", "Bernardo O'Higgins"))
    }
    
    
    // ["a" "b" "c"]
    // ["" "man " "plan " "canal panama"]
    // [" " "x" "y" "z" " "]
    // [""]
    
  • Join:Join 连接其第一个参数的元素以创建单个字符串。分隔符字符串 sep 放置在结果字符串中的元素之间。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        s := []string{"foo", "bar", "baz"}
        fmt.Println(strings.Join(s, ", "))
    }
    
    
    // foo, bar, baz
    
  • Contains:包含报告 substr 是否在 s 内。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        fmt.Println(strings.Contains("seafood", "foo"))
        fmt.Println(strings.Contains("seafood", "bar"))
        fmt.Println(strings.Contains("seafood", ""))
        fmt.Println(strings.Contains("", ""))
    }
    
    
    // true
    // false
    // true
    // true
    
  • Index:Index 返回 s 中 substr 的第一个实例的索引,如果 s 中不存在 substr,则返回 -1。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        fmt.Println(strings.Index("chicken", "ken"))
        fmt.Println(strings.Index("chicken", "dmr"))
    }
    
    
    // 4
    // -1
    
  • ToLower:将符文映射为小写。
  • ToUpper:将符文映射为大写。
  • Trim:Trim 返回字符串 s 的切片,其中删除了 cutset 中包含的所有前导和尾随 Unicode 代码点。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        fmt.Print(strings.Trim("¡¡¡Hello, Gophers!!!", "!¡"))
    }
    
    
    // Hello, Gophers
    
  • TrimRight:TrimRight 返回字符串 s 的一个切片,其中包含在 cutset 中的所有尾随 Unicode 代码点都被删除。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        fmt.Print(strings.TrimRight("¡¡¡Hello, Gophers!!!", "!¡"))
    }
    
    
    // ¡¡¡Hello, Gophers
    
  • TrimLeft:TrimLeft 返回字符串 s 的切片,其中包含在切割集中的所有前导 Unicode 代码点都已删除。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        fmt.Print(strings.TrimLeft("¡¡¡Hello, Gophers!!!", "!¡"))
    }
    
    
    // Hello, Gophers!!!