zoukankan      html  css  js  c++  java
  • Golang 数组、切片、映射

    定义数组

    var arr1 [5]int   //整型类型
    fmt.Println(arr1) //[0 0 0 0 0]
    //赋值
    arr1 = [5]int{1, 2, 3, 4, 5}
    fmt.Println(arr1) //[1 2 3 4 5]
    
    var arr2 [6]*int  //整型指针数组
    fmt.Println(arr2) //[<nil> <nil> <nil> <nil> <nil> <nil>]
    
    var arr3 [2][3]int //二维数组
    fmt.Println(arr3)  //[[0 0 0] [0 0 0]]
    
    //	使用简短的格式
    arr4 := [5]int{2, 4, 6, 8, 10}
    fmt.Println(arr4) //[2 4 6 8 10]
    
    //其他方式,如果长度的位置是... 表示数组长度是根据后面的数据元素个数来计算
    arr5 := [...]int{2, 3, 4, 5, 6, 7}
    fmt.Println(arr5, len(arr5)) //[2 3 4 5 6 7]  6
    
    //	指定数组的索引来赋值
    arr6 := [...]int{5: 10, 7: 23}
    //将数组下标为5的元素赋值为10,将数组下标为7的元素赋值为23
    //数组长度为8
    fmt.Println(arr6, len(arr6)) //[0 0 0 0 0 10 0 23] 8
    
    arr7 := [2][3]int{{1, 2, 3}, {4, 5, 6}}
    fmt.Println(arr7) //[[1 2 3] [4 5 6]]
    

      

    数组访问与数组长度

    arr1 := [5]int{2, 4, 6, 8, 10}
    fmt.Println(arr1)                 // [2 4 6 8 10]
    fmt.Println("length:", len(arr1)) //length: 5
    //	arr1[5] = 100  //出错,数组越界
    arr1[0] = 99
    fmt.Println(arr1) //[99 4 6 8 10]
    
    arr2 := [2][3]int{{1, 2, 3}, {4, 5, 6}}
    fmt.Println(len(arr2))    //2
    fmt.Println(len(arr2[0])) //3
    fmt.Println(arr2[1][1])   //5
    

      

    数组遍历

    arr1 := [5]int{2, 4, 6, 8, 10}
    for i := 0; i < len(arr1); i++ {
    	fmt.Println(arr1[i]) //2 4 6 8 10
    }
    for i, v := range arr1 {
    	fmt.Print(i, "=>", v) // 0=>2,1=>4,2=>6,3=>8,4=>10
    }
    //	不需要索引的时候,可以将用_代替i
    for _, v := range arr1 {
    	fmt.Println(v) //2,4,6,8,10
    }
    

      

    数组作为函数参数

      数组作为函数作为参数时,如果是给形参传递数组名,那么就是传值操作,传递的是数组的副本,修改副本的内容,并不会影响实参。

      要想在函数中对数组的修改作用到实参,可以用数组指针,即->使用指针的形式,将数组的地址传递给函数,并且函数定义时,接收一个指针类型的参数,那么就可以对数组内部进行修改,但是不能修修改数组长度。

    package main
    
    import "fmt"
    
    func Double(arr [5]int) [5]int {
    	for i := 0; i < 5; i++ {
    		arr[i] *= 2
    	}
    	return arr
    }
    
    //接收的指针类型,即数组的地址
    //注意这里的形参要写成 arr *[5]int   不要写成arr [5]*int
    //arr [5]*int表示的是有五个元素的数组,每个元素是一个指针,即5个指针
    //arr *[5]int表示的是一个指针,这一个指针指向一个拥有5个元素的数组,每个元素时一个int型变量
    func Triple(arr *[5]int) {
    	for i := 0; i < 5; i++ {
    		arr[i] *= 3
    	}
    }
    func main() {
    	var arr2 [6]*int  //整型指针数组
    	fmt.Println(arr2) //[<nil> <nil> <nil> <nil> <nil> <nil>]
    	arr := [5]int{1, 2, 3, 4, 5}
    	fmt.Println(arr) //[1 2 3 4 5]
    
    	arr1 := Double(arr)
    	fmt.Println(arr1) //[2 4 6 8 10]
    	fmt.Println(arr)  //[1 2 3 4 5]
    
    	Triple(&arr)
    	fmt.Println(arr) //[3 6 9 12 15]
    }
    

      

    数组类型、数组比较

      数组的长度一旦确定,就不能再改变。如果要改变,只能转换为slice,但是用了slice之后,改变的是slice的长度,但是数组长度始终不变。

      数组长度不同,那么数组就不是同一个类型,不能相互赋值-->参数传递。

      相同类型的数组可以进行比较,这里的类型不只是数组元素的类型,也包括数组的长度都要相同,才能进行比较。

    package main
    import "fmt"
    func Double(arr [5]int) [5]int {
    	for i := 0; i < 5; i++ {
    		arr[i] *= 2
    	}
    	return arr
    }
    
    func main() {
    	arr1 := [5]int{1, 2, 3, 4, 5}
    	Double(arr1) //正确   形参和实参都是[5]int类型,注意[5]int是一个类型
    
    	arr2 := [6]int{1, 2, 3, 4, 5, 6}
    	Double(arr2) //错误,不能将类型为[6]int的实参,赋值给类型为[5]int的形参
    	//[5]int和[6]int是两个不同的类型
    }
    

      

      

    创建切片

    var slice []int
    //定义一个空切片,注意上面[]中没有指定长度,如果指定长度,就代表是数组了
    fmt.Println(slice) //[]
    
    slice1 := []int{1, 2, 3, 4, 5}
    //创建一个长度和容量为5的切片
    fmt.Println(slice1)                   //[1 2 3 4 5]
    fmt.Println(len(slice1), cap(slice1)) //5 5
    
    slice2 := []int{5: 10}
    //创建一个长度和容量为6的切片
    fmt.Println(slice2)                   //[0 0 0 0 0 10]
    fmt.Println(len(slice2), cap(slice2)) //6 6
    
    //使用make创建切边
    //make(type,len,cap),未指定cap是,cap和len相等
    slice3 := make([]int, 5, 10)
    fmt.Println(slice3, len(slice3), cap(slice3)) //[0 0 0 0 0] 5 10
    slice4 := make([]int, 6)
    fmt.Println(slice4, len(slice4), cap(slice4)) //[0 0 0 0 0 0] 6 6
    
    //	利用数组创建切片
    //[strat:end]左闭右开,start省略时,默认为0;end省略时默认为数组或者切片长度
    arr := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    slice5 := arr[3:]
    fmt.Println(slice5)  //[3 4 5 6 7 8 9]
    
    slice6 := arr[:7]
    fmt.Println(slice6)  //[0 1 2 3 4 5 6]
    
    slice7 := arr[4:8]
    fmt.Println(slice7)  //[4 5 6 7]
    
    slice8 := arr[:]
    fmt.Println(slice8)  //[0 1 2 3 4 5 6 7 8 9]

      通过len函数求的切片长度,判断是否为空。

    append函数

      使用append函数后,返回的是一个slice类型,不是数组类型

    slice := []int{1, 2, 3, 4, 5}
    fmt.Println(slice) //[1 2 3 4 5]
    
    //追加元素
    slice = append(slice, 6)
    fmt.Println(slice) //[1 2 3 4 5 6]
    
    //追加切片
    s1 := []int{99, 100}
    //注意下面的...表示解构,即,将切片的内容展开后填充到该位置
    slice = append(slice, s1...)
    fmt.Println(slice)
    

      不能对数组调用append函数,即,append函数的第一个参数必须是slice。

    copy函数

      copy(destination,resource),复制之后,dest的长度并不会改变,即使复制给他的切片长度远大于它。

    //长的slice复制到短的slice
    s1 := []int{1, 2, 3, 4, 5}
    s2 := []int{10, 20, 30, 40}
    copy(s2, s1)
    fmt.Println(s2) //[1 2 3 4]
    
    //短的slice复制到长的slice
    s3 := []int{2, 3, 4}
    s4 := []int{9, 8, 7, 6, 5}
    copy(s4, s3)
    fmt.Println(s4) //[2 3 4 6 5]
    
    //相同长度的slice进行复制
    s5 := []int{1, 2, 3}
    s6 := []int{4, 5, 6}
    copy(s6, s5)
    fmt.Println(s6) //[1 2 3]
    

      不能使用copy进行数组的复制操作,即,copy的两个参数都必须是slice。

    slice作为函数参数

      将数组传递给函数之后,在函数中操作的是数组的副本。虽然可以使用数组指针形式传递,但是更通用的是使用slice,使用slice之后,可以通过在函数中修改slice,来达到修改数组的目的。

    package main
    
    import "fmt"
    
    //参数是数组类型
    func Double(arr [5]int) {
    	for i := 0; i < 5; i++ {
    		arr[i] *= 2
    	}
    }
    
    //类型是slice类型
    func Triple(slice []int) {
    	for i := 0; i < len(slice); i++ {
    		slice[i] *= 3
    	}
    }
    func main() {
    	arr := [5]int{1, 2, 3, 4, 5}
    	Double(arr)
    	fmt.Println(arr)  //[1 2 3 4 5]
    
    	//数组转换为切片
    	slice := arr[:]
    	Triple(slice)
    	fmt.Println(arr)  //[3 6 9 12 15]
    }
    

      

    创建map

    //定义空的映射,默认值为nil
    var m1 map[int]string
    fmt.Println(m1) //map[]
    //再进行初始化
    m1 = map[int]string{
    	1: "hello",
    	8: "world", //注意这种写法,末尾的逗号不可省
    }
    fmt.Println(m1) //map[1:hello 8:world]
    
    //使用make创建映射,注意此时最多只用两个参数,
    //一个是map的映射类型,一个map的容量,容量可以省略
    //但是没有len这一个参数,即不能指定长度这一项
    m2 := make(map[int]string, 100)
    fmt.Println(m2, len(m2))
    
    m3 := make(map[string][]string)
    m3["server"] = []string{"apache", "nginx"}
    m3["language"] = []string{"php", "golang", "python"}
    fmt.Println(m3) //map[server:[apache nginx] language:[php golang python]]
    
    //创建映射,同时初始化,此时不需要使用make
    m4 := map[int]string{1: "demo", 2: "test"}
    fmt.Println(m4) //map[1:demo 2:test]
    

      

    删除map元素

    //字符串映射到string类型的切片
    m1 := map[string][]string{
    	"server":   []string{"apache", "nginx"},
    	"language": []string{"php", "python", "golang"},
    }
    fmt.Println(m1) //map[server:[apache nginx] language:[php python golang]]
    
    //删除没有的key,不报错
    delete(m1, "client")
    fmt.Println(m1) //map[server:[apache nginx] language:[php python golang]]
    
    delete(m1, "server")
    fmt.Println(m1) //map[language:[php python golang]]
    

      

    查找map元素

    //字符串映射到string类型的切片
    m1 := map[string][]string{
    	"server":   []string{"apache", "nginx"},
    	"language": []string{"php", "python", "golang"},
    }
    fmt.Println(m1) //map[server:[apache nginx] language:[php python golang]]
    
    //访问一个不存在的元素,不会报错,返回类型零值
    fmt.Println(m1["client"]) //[]
    
    v, exists := m1["client"]
    fmt.Println(v, exists) //[] false
    
    v, exists = m1["server"]
    fmt.Println(v, exists) //[apache nginx] true
    

      

    遍历map

    //字符串映射到string类型的切片
    m1 := map[string][]string{
    	"server":   []string{"apache", "nginx"},
    	"language": []string{"php", "python", "golang"},
    }
    for key, value := range m1 {
    	fmt.Println(key, "=>", value)
    }
    //server => [apache nginx]
    //language => [php python golang]
    

      映射是无序的,所以遍历多次的结果,元素的顺序不一定完全相同

    map注意事项

      1、map之间不能进行比较,但是可以和nil进行比较

      2、不能对map取地址,因为map本就是引用类型

    var m0 map[int]string
    fmt.Println(m0 == nil) //true
    
    var m1 map[int]string
    fmt.Println(m0 == m1) //不能进行比较,会报错
    
    m2 := map[int]string{1: "one", 2: "two"}
    fmt.Println(m2 == nil) //false
    

      

    map作为函数参数

    package main
    
    import "fmt"
    
    //接受一个map
    func Show(m map[int]string) {
    	m[1] = "three"
    	m[3] = "four"
    }
    func main() {
    	m1 := map[int]string{
    		1: "one",
    		2: "two",
    	}
    	fmt.Println(m1) //map[1:one 2:two]
    
    	Show(m1)
    	fmt.Println(m1) //map[3:four 1:three 2:two]
    }
    

      将map作为函数的参数,在函数中修改map,会直接影响到实参,因为map是引用类型。

      

  • 相关阅读:
    运算符优先级
    Tips—查询某结构体
    在线词典--(一、流程分析)
    数据库—SQLite3
    回调函数(转载)
    UNIX域套接字
    进程间通信小结
    HDU_oj_2027 统计元音
    HDU_oj_2026 首字母变大写
    HDU_oj_2025 查找最大字母
  • 原文地址:https://www.cnblogs.com/-beyond/p/8110634.html
Copyright © 2011-2022 走看看