06、Golang 教程 - 内建容器

数组

 func main() {

    //数组的定义方式
    //[0,0,0]
    var nums1 [3]int
    nums2 := [3]int{

     1, 2, 3}
    // 如果要让编译器判断我们有几个元素,要用...  没有...是切片
    nums3 := [...]int{

     3, 4, 5}
    fmt.Println(nums1, nums3, nums2)
    // 遍历方式
    // 第一种
    for i:=0;i<len(nums3);i++{

        fmt.Println(nums3[i])
    }

    // i为索引
    for i :=range nums2{

        fmt.Println(i)
    }

    // i为索引 v为值
    for i, v:=range nums2{

        fmt.Println(i,v)
    }

    // 丢弃索引
    for _, v:=range nums2{

        fmt.Println(v)
    }
    // 数组是值类型
}
// 数组是值类型,作为参数会拷贝整个数组
// [3]int [5]int是不同的类型,这个函数只能传入[5]int类型
// 数组是值类型,所以在函数内修改数组的值并不会影响到实参
func printArray(arr [5]int) {

 arr[3] = 100 //不会影响到实参
}
func printArray2(arr *[5]int) {

      //传入指针
    arr[3] = 100 //这样就可以改变值,很灵活,不用在arr前面加上*
    (*arr)[3] = 100 // 这样也可以
}
// 在go语言中一般不直接使用数组

切片-Slice

 func main() {

    // 切片 左开右闭
    arrList := [7]int{

     1,2,3,4,5,6,7}
    arr := arrList[:] // 定义一个切片
    arr1 := arrList[2,6] // arr1 [3,4,5,6]
    arr1[0] = 22  //arrList [1,2,22,4,5,6,7]
    sliceLearn(arr) //arrList [22,2,22,4,5,6,7]

    //切片可以对切片处理
    arr3 := arr1[1,3] //arr3 [4,5]
    arr4 := arr3[0:4] // arr4 [4,5,6,7]
}

// slice 切片
// slice相当于数组的一个view
// slice 定义 arr []int
func sliceLearn(arr []int){

    arr[0]=22 // 会改变值,而且会影响实参数
}

//Slice本身没有数据,是对底层array的一个view
  • Slice的实现
 // slice可以向后扩展,但不可以向前扩展

struct {

    ptr // 指向数组中切片第一个元素的指针
    len //slice视图的数据
    cap // 底层数组的长度
}
// reslice 扩展不能超过cap的长度 s[i] 不能超过len的长度
// %v value的值 %T 类型
// 一个切片s可以扩展到他的大小上限:s = s[:cap(s)], 如果再扩大的话就会报运行时错误
  • slice的一些操作
 // 向Slice添加元素
// 添加元素时如果超过了cap,系统会重新分配更大的底层数组 然后把值拷贝过去
func main() {

    arr := [6]int{

     1, 2, 3, 4, 5, 6}
    slice1 := arr[2:5]
    slice2 := append(slice1, 11)        // 把6变成11
    slice3 := append(slice2, 12)        //分配一个更长的arr 然后slice3 view他
    fmt.Println(slice1, slice2, slice3) // [3 4 5] [3 4 5 11] [3 4 5 11 12]
    fmt.Println(arr)                    //[1 2 3 4 5 11]

    // 由于是值传递,所以必须接收append的值

    // 直接创建slice
    var s []int             // nil
    s1 := []int{

     2, 3, 4, 5} // 这样也可以
    s2 := make([]int, 16)
    s3 := make([]int, 16, 32)
    for i := 0; i < 100; i++ {

        printSlice(s)
        s = append(s, 2*i)
    }
    fmt.Println(s)

    copy(s2,s1) // dst scr
    //删除一个元素
    s2 = append(s2[:3],s2[4:]...)//把位置为3的删掉
    s2 = s2[1:] //删除头
    s2 = s2[:len(s2)-1] //删除尾

}

func printSlice(s []int) {

    fmt.Printf(" len=%d, cap=%d\n", len(s), cap(s))
    // len=6, cap=8
    // len=7, cap=8
    // len=8, cap=8
    // len=9, cap=16
    // len=10, cap=16
}

Map

 map[k]V
map[k]map[k2]V
 func main() {

    m1 := map[string]string{

        "aa": "bb",
        "bb": "cc",
    }
    m2 := make(map[string]string) // m2 == empty map
    var m3 map[string]string      //m3 == nil

    fmt.Println(m1, m2, m3) //map[aa:bb bb:cc] map[] map[]

    //遍历 无序 每次顺序不一样
    for k, v := range m1 {

        fmt.Println(k, v)
    }
    // key
    for k := range m1 {

        fmt.Println(k)
    }
    // 打印一个不存在的key 会是zero value
    fmt.Println(m1["abc"])
    courseName, ok := m2["abc"] // 第二个为true 表示值存在,false表示不存在
    fmt.Println(courseName, ok) // false
    delete(m1,"abc") // 删除元素
}
  • 创建:make(map[string]int)
  • 获取元素 m[key]
  • key不存在时获取value类型的初始值
  • 用value, ok := m[key]来判断是否存在key
  • 用delete删除一个key
  • map遍历不保证顺序,可以用len来获取个数
  • map使用的是哈希表,key必须可以比较相等
  • 除了slice, map, function的内建类型都可以作为key
  • struct类型不包含上述字段,也可以作为key
  • 每个rune是4个字节,转rune 不是对原有的内存存的东西进行解释,而是重新开一个内存,然后解释后存起来

rune

  • rune相当于go的char
  • 使用range遍历pos(索引不连续),rune(索引连续)对
  • 使用utf8.RuneCountInString获得字符数量
  • 使用len获得字节长度
  • 使用[]byte获得字节
 func main() {

    s := "yes!肖小小最棒"
    fmt.Printf("%s\n", []byte(s)) //yes!肖小小最棒
    for _, b := range []byte(s) {

        // utf-8 可变长
        fmt.Printf("%X ", b) //79 65 73 EF BC 81 E8 82 96 E5 B0 8F E5 B0 8F E6 9C 80 E6 A3 92
    }
    fmt.Println()

    for i, ch := range s {

      // ch is a rune
        // i为索引 第几个字节开始 ch为unicode编码
        //(0,79)(1,65)(2,73)(3,FF01)(6,8096)(9,5C0F)(12,5C0F)(15,6700)(18,68D2)
        fmt.Printf("(%d,%X)", i, ch)
    }
    fmt.Println()
    // 9
    fmt.Println(utf8.RuneCountInString(s))

    bytes := []byte(s)

    for len(bytes) > 0 {

        ch, size := utf8.DecodeRune(bytes) // ch is rune  size 为ch的字节长度
        bytes = bytes[size:]
        fmt.Printf("%c", ch)

    }
    fmt.Println()

    for i, ch := range []rune(s) {

        // 下标连续
        // (0,y)(1,e)(2,s)(3,!)(4,肖)(5,小)(6,小)(7,最)(8,棒)
        fmt.Printf("(%d,%c)", i, ch)
    }
    fmt.Println()
}