Go学习第二章内建容器

2.1.数组

数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,数组元素可以通过索引来读取(或修改),定义方法:

package main
 
import (
    "fmt"
)
 
func main() {
    //var定义数组可不赋初值
    var arr1 [5]int                  //[0 0 0 0 0]
    //冒号定义需指定初值
    arr2 := [3]int{1,3,5}            //[1 3 5]
    //...表示任意个数
    arr3 := [...]int{2,4,6,8,10}     //[2 4 6 8 10]
    fmt.Println(arr1,arr2,arr3)
    //数组的遍历可获取下标和值,不想取可用_符号
    for i,v := range arr3{
        fmt.Println(i,v)
    }  
}

数组是值类型,传递到函数中会复制一份而不会修改原值并且[10]int和[20]int不是同一类型:

package main
 
import (
    "fmt"
)
 
func printArray(arr [5]int){
   arr[1] = 100
}
 
func main() {
    arr2 := [3]int{1,3,5}
    //arr3 := [...]int{2,4,6,8,10}
    printArray(arr2)     //报错
}

2.2.切片

切片是数组的抽象,数组的长度不可改变,与数组相比切片(动态数组)的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大,定义方式:

package main
 
import "fmt"
 
func main() {
    arr := []int{0,1,2,3,4,5,6,7} // 声明一个未指定大小的数组来定义切片
    fmt.Println(arr[:6])   
    arr2 := make([]int,16) // 通过make函数,后面是长度
    fmt.Printf("len(s3)=%d,cap(s3)=%d
",len(s3),cap(s3))    //len(s3)=16,cap(s3)=16
    arr3 := make([]int,16,32) // 也可以指定容量
    fmt.Printf("len(s4)=%d,cap(s4)=%d
",len(s4),cap(s4))    //16,32  
}

切片的扩展可以向后,不可以向前扩展:

package main
 
import "fmt"
 
func main() {
    arr := [...]int{0,1,2,3,4,5,6,7}
    s1 := arr[2:4]
    s2 := s1[3:5]
    fmt.Println("arr = ",arr)                                         //arr =  [0 1 2 3 4 5 6 7]
    fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d
",s1,len(s1),cap(s1))   //s1=[2 3],len(s1)=2,cap(s1)=6
    fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d
",s2,len(s2),cap(s2))   //s2=[5 6],len(s2)=2,cap(s2)=3
    fmt.Println(s1[3:6])                                             //[5 6 7]
}

切片增加元素时,如果超出了容量,系统会重新分配更大的底层数组,由于是值传递,增加元素时必须接收返回值:

package main
 
import "fmt"
 
func main() {
    arr := [...]int{0,1,2,3,4,5,6,7}
    s1 := arr[2:6]         //[2 3 4 5]
    s2 := s1[3:5]          //[5 6]
    s3 := append(s2,10)
    s4 := append(s3,11)
    fmt.Println(s1,s2,s3,s4) //[5 6 10] [5 6 10 11]
    //因为s2的容量是[5,6,7],append把7替换成10,s4超出了容量
    fmt.Println(arr)         //[0 1 2 3 4 5 6 10]
}

2.3.Map

map是一种无序的键值对的集合,Map 最重要的是通过key来快速检索数据,定义方式:

package main
 
import "fmt"
 
func main() {
    // map关键字定义 括号是key类型外面的string是值类型
    m1 := map[string]string{
        "name":   "derek",
        "course": "go",
        "city":   "guangdong",
    }
    fmt.Println(m1)         //map[city:guangdong course:go name:derek]
 
    //通过make函数定义
    m2 := make(map[string]int)
    fmt.Println(m2)          //map[]
}

map的使用:

package main
 
import "fmt"
 
func main() {
    m1 := map[string]string{
        "name":   "derek",
        "course": "go",
        "city":   "guangdong",
    }
    m1["sale"] = "boby" //插入

    sale, ok := m1["sale"]     //检查是否存在元素 存在ok为True 否则sale的值为空
    fmt.Println(sale,ok) // boby,true

    delete(m1,"sale") //删除
    fmt.Println(m1) 
    for k,v := range m1{
        fmt.Println(k,v)  //遍历
    }
}

 2.4.new和make

由于引用数据类型(slice,map,channel等)和指针必须在创建内存后才可使用,所以把一个无初始数据的引用数据类型赋值给变量需要使用make函数分配空间:

var userInfo = make(map[string]string)
userInfo["userName"] = "zhangsan"
fmt.Println(userInfo)

var array = make([]int, 4, 4) // 切片slice
array[0] = 1
fmt.Println(array)

new用于类型的内存分配,返回的是指向类型的指针,make用于slice.map.channel的初始化,返回的是引用类型的本身:

// 指针变量初始化错误方法 会报错
var a *int
*a = 100
fmt.Println(a)

// 使用new关键字创建指针
aPoint := new(int)
bPoint := new(bool)
fmt.Printf("%T 
", aPoint) // 下面四个值*int  *bool  0 false
fmt.Printf("%T 
", bPoint)
fmt.Println(*aPoint)
fmt.Println(*bPoint)
原文地址:https://www.cnblogs.com/hacknoone/p/13454533.html