• 数组,切片


    1、数组

    数组属于值类型。

    1)声明

    var 数组变量名 [元素数量]Type

    • 数组变量名:数组声明及使用时的变量名。
    • 元素数量:数组的元素数量,可以是一个表达式,但最终通过编译期计算的结果必须是整型数值,元素数量不能含有到运行时才能确认大小的数值。
    • Type:可以是任意基本类型,包括数组本身,类型为数组本身时,可以实现多维数组。

    默认情况下,数组的每个元素都会被初始化为元素类型对应的零值,对于数字类型来说就是 0,同时也可以使用数组字面值语法,用一组值来初始化数组。

    在数组的定义中,如果在数组长度的位置出现“...”省略号,则表示数组的长度是根据初始化值的个数来计算。

    示例:

    package main
    
    import "fmt"
    
    func main() {
    	var a [3]int
    	for i := 0; i < len(a);  i++{
    		fmt.Printf("%d, %d
    ", i, a[i])
    	}
    	var b = [3]int{1, 2}
    	fmt.Println("----------------------------")
    	for i := 0; i < len(b);  i++{
    		fmt.Printf("%d, %d
    ", i, b[i])
    	}
    	c := [...]int{1, 2, 3}
    	fmt.Println("----------------------------")
    	for i := 0; i < len(c);  i++{
    		fmt.Printf("%d, %d
    ", i, c[i])
    	}
    }
    

      

    2)比较两个数组是否相等

    如果两个数组类型相同(包括数组的长度,数组中元素的类型)的情况下,我们可以直接通过较运算符(== 和!=)来判断两个数组是否相等,只有当两个数组的所有元素都是相等的时候数组才是相等的,不能比较两个类型不同的数组,否则程序将无法完成编译。

    数组类型相同的数组之间可以互相赋值。

    3)多维数组

    示例:

    package main
    
    import "fmt"
    
    func output(str string, arr [4][2]int)  {
    	fmt.Printf("ArrName: %s
    ", str)
    	for i := 0; i < 4; i++{
    		for j := 0; j < 2 ; j++  {
    			fmt.Printf("%d, ", arr[i][j])
    		}
    		fmt.Println()
    	}
    }
    
    func main() {
    	// 声明一个二维整型数组,两个维度的长度分别是 4 和 2
    	var a [4][2]int
    	output("a", a)
    	// 使用数组字面量来声明并初始化一个二维整型数组
    	b := [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}}
    	output("b", b)
    	// 声明并初始化数组中索引为 1 和 3 的元素
    	c := [4][2]int{1: {20, 21}, 3: {40, 41}}
    	output("c", c)
    	// 声明并初始化数组中指定的元素
    	d := [4][2]int{1: {0: 20}, 3: {1: 41}}
    	output("d", d)
    }
    

      

     2、切片

    切片(slice)是对数组的一个连续片段的引用,所以切片是一个引用类型。Go语言中切片的内部结构包含地址、大小和容量,切片一般用于快速地操作一块数据集合。

    1)从数组或切片生成新的切片

    从连续内存区域生成切片是常见的操作,格式如下:

    slice [开始位置 : 结束位置]

    • slice:表示目标切片对象;
    • 开始位置:对应目标切片对象的索引;
    • 结束位置:对应目标切片的结束索引。

    从数组或切片生成新的切片拥有如下特性:

    • 取出的元素数量为:结束位置 - 开始位置;
    • 取出元素不包含结束位置对应的索引,切片最后一个元素使用 slice[len(slice)] 获取;
    • 当缺省开始位置时,表示从连续区域开头到结束位置;
    • 当缺省结束位置时,表示从开始位置到整个连续区域末尾;
    • 两者同时缺省时,与切片本身等效;
    • 两者同时为 0 时,等效于空切片,一般用于切片复位。

    示例:

    package main
    
    import "fmt"
    
    func main() {
    	var a = [3]int{1,2,3}
    	fmt.Println(a[1:2])
    	fmt.Println(a[:3])
    	fmt.Println(a[0:])
    }
    

      

    2)直接声明切片

    除了可以从原有的数组或者切片中生成切片外,也可以声明一个新的切片,每一种类型都可以拥有其切片类型,表示多个相同类型元素的连续集合,因此切片类型也可以被声明,切片类型声明格式如下:

    var name []Type

    切片是动态结构,只能与 nil 判定相等,不能互相判定相等。

    声明新的切片后,可以使用 append() 函数向切片中添加元素。

    示例:

    package main
    
    import "fmt"
    
    func main() {
    	var a []int // 声明但未使用的切片的默认值是 nil
    	var b = []int{} // 已经分配了内存
    	fmt.Println(a == nil) // true
    	fmt.Println(b == nil) // false
    }
    

      

    3)使用make()函数构造切片

    如果需要动态地创建一个切片,可以使用 make() 内建函数,格式如下:

    make( []Type, size, cap )

    其中 Type 是指切片的元素类型,size 指的是为这个类型分配多少个元素,cap 为预分配的元素数量,这个值设定后不影响 size,只是能提前分配空间,降低多次分配空间造成的性能问题。

    注意:使用 make() 函数生成的切片一定发生了内存分配操作,但给定开始与结束位置(包括切片复位)的切片只是将新的切片结构指向已经分配好的内存区域,设定开始与结束位置,不会发生内存分配操作。

    示例:

    package main
    
    import "fmt"
    
    func main() {
    	a := make([]int, 2, 10)
    	fmt.Println(a)
    	fmt.Println("len=", len(a))
    	fmt.Println("cap=", cap(a))
    }
    

      

     4)添加元素

    Go语言的内建函数 append() 可以为切片动态添加元素,在使用 append() 函数为切片动态添加元素时,如果空间不足以容纳足够多的元素,切片就会进行“扩容”,此时新切片的长度会发生改变。

    尾部添加元素示例:

    package main
    
    import "fmt"
    
    func main() {
    	var a []int
    	a = append(a, 1) // 追加1个元素
    	a = append(a, 1, 2) // 追加多个元素
    	a = append(a, []int{1, 2, 3}...) // 追加一个切片
    	fmt.Println(a)
    }
    

      

    头部添加元素示例:

    package main
    
    import "fmt"
    
    func main() {
    	var a = []int{1, 2, 3}
    	a = append([]int{1}, a...) // 在开头添加1个元素
    	a = append([]int{1, 2}, a...) // 在开头添加1个切片
    	fmt.Println(a)
    }
    

      

    切片中间插入元素示例:

    package main
    
    import "fmt"
    
    func main() {
    	var a = []int{1, 2, 3, 4, 5}
    	// 在第2个位置插入一个切片
    	a = append(a[:2], append([]int{998, 999}, a[2:]...)...)
    	/*
    	每个添加操作中的第二个 append 调用都会创建一个临时切片,并将 a[i:] 的内容复制到新创建的切片中,
    	然后将临时创建的切片再追加到 a[:i] 中。
    	*/
    	fmt.Println(a)
    }
    

      

    5)切片复制

    Go语言的内置函数 copy() 可以将一个数组切片复制到另一个数组切片中,如果加入的两个数组切片不一样大,就会按照其中较小的那个数组切片的元素个数进行复制。

    copy() 函数的使用格式:copy( destSlice, srcSlice []T) int

    其中 srcSlice 为数据来源切片,destSlice 为复制的目标(也就是将 srcSlice 复制到 destSlice),来源和目标的类型必须一致,copy() 函数的返回值表示实际发生复制的元素个数。

    示例:

    package main
    
    import "fmt"
    
    func main() {
    	slice1 := []int{1,2,3,4,5}
    	slice2 := []int{100, 101, 102}
    	count := copy(slice2, slice1)
    	fmt.Println(count)
    	count = copy(slice1, slice2)
    	fmt.Println(count)
    }
    

      

  • 相关阅读:
    2021年Web开发的7大趋势
    webpack4.0各个击破(9)—— karma篇
    Webpack4.0各个击破(8)tapable篇
    你应该了解的25个JS技巧
    Webpack4.0各个击破(7)plugin篇
    Webpack4.0各个击破(5)module篇
    webpack4.0各个击破(4)—— Javascript & splitChunk
    webpack4.0各个击破(3)—— Assets篇
    10 张图聊聊线程的生命周期和常用 APIs
    新手一看就懂的线程池!
  • 原文地址:https://www.cnblogs.com/ACGame/p/11875932.html
Copyright © 2020-2023  润新知