zoukankan      html  css  js  c++  java
  • go语言之数组

    1、go语言的数组和python的列表不一样,python的列表没有限定类型,而go的数组限定的类型,理由是这样的,请看下面的图

    go语言的数组会数组中第一个值的内存地址,在我们上面的例子中,数组中的元素是整型,一个整型占4个字节,那么第一个值的内存地址起始地址比如是0x25,那么第二个值的内存起始地址就是0x29,这样以此类推,我们就可以拿到这个数组中的所有的值,这也是为什么go语言不支持不同类型的值在一个数组中的缘故

    在看我们的python,python的内部会在维护一个数组,这个数组是数组中每个元素的内存地址,这样,就可以使得python的数组支持不同类型的元素,因为他实际维护了2个数组,一个是真正数据的数组,一个是真正数据的内存地址的数组

    通过上面的解释,大家应该知道为什么python的列表支持不同类型了吧,同样带来的后果肯定是更大的内存消耗和更大的性能消耗

    2、go语言的数组

    package main
    
    import "fmt"
    
    //go语言的数组类似python中的列表
    
    //申明数组
    //var 数组名[数组长度] 数组类型
    
    
    //数组的长度定好之后不能修改
    
    
    //go语言的数组定义了类型,就只能存储这种类型,不能存储其他类型
    func main() {
    	//首先定义一个一维数组
    
    	//定义一个int类型的数组
    
    	var arr1 [5] int
    
    
    	//申明加赋值数组
    	arr2 := [5]int{1,2,3,4,5}
    
    	//可以省略大小
    	arr3 := [...]int{1,2,3,4,5}
    
    
    	arr4 := [10]int{1,2,3,4,5}
    
    	fmt.Println(arr1,arr2,arr3,arr4)
    
    	//[0 0 0 0 0] [1 2 3 4 5] [1 2 3 4 5] [1 2 3 4 5 0 0 0 0 0]
    
    
    
    
    	//定义一个二维数组,四行五列的数组,一般也用的比较少
    
    	var grid [4][5] int
    	fmt.Println(grid)
    	//[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
    
    
    	//数据的遍历,一个for一个range
    	//方式1
    	for i :=0;i < len(arr3);i++{
    		fmt.Println(i,arr3[i])
    	}
    
    
    	//方式2
    	for i := range arr3 {
    		fmt.Println(i,arr3[i])
    	}
    
    	for i,v := range arr3 {
    		fmt.Println(i,v)
    	}
    
    
    
    }
    

      

    3、go语言的数组是值类型,不是引用

    package main
    
    import "fmt"
    
    func printArr(arr [5]int)  {
    	arr[0] = 100
    
    	fmt.Println(arr)
    
    }
    
    func main() {
    	//var arr1 [5] int
    
    	//printArr(arr1)
    	//[100 0 0 0 0]
    	//fmt.Println(arr1)
    	//[0 0 0 0 0]
    
    
    	//报错
    	//arr2 := [3]int{1,2,3}
    	//printArr(arr2)
    //	.	est20.go:23:10: cannot use arr2 (type [3]int) as type [5]int in argument to printAr
    
    	arr3 := [...]int{1,2,3,4,5}
    
    	printArr(arr3)
    	//[100 2 3 4 5]
    
    	fmt.Println(arr3)
    	//[1 2 3 4 5]
    }
    

      

    上面的例子中我们传递一个数组给函数,在函数中修改了这个数组中的值,对原来的数组是没有影响的,说明传递进去的数组是一个全新的数组,和原来的数组没有关系

    4、一个函数接受一个指针作为参数

    //这个函数接受一个指针作为参数
    func printArr2(arr *[5]int)  {
    	arr[0] = 100
    
    	fmt.Println(*arr)
    
    }
    

      

    调用这个函数

    	arr3 := [...]int{1,2,3,4,5}
    
    	//printArr(arr3)
    	//[100 2 3 4 5]
    
    	//fmt.Println(arr3)
    	//[1 2 3 4 5]
    
    
    	//如果传递一个指针进去,则在函数中修改这个指针指向的数组,外面的数组也会同步修改
    	printArr2(&arr3)
    
    	fmt.Println(arr3)
    

      

    结果如下

    [100 2 3 4 5]
    [100 2 3 4 5]

    菜鸟教程中的数组的讲解

    Go 语言数组

    Go 语言提供了数组类型的数据结构。

    数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型。

    相对于去声明 number0, number1, ..., number99 的变量,使用数组形式 numbers[0], numbers[1] ..., numbers[99] 更加方便且易于扩展。

    数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。

    声明数组

    Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:

    var variable_name [SIZE] variable_type
    

    以上为一维数组的定义方式。例如以下定义了数组 balance 长度为 10 类型为 float32:

    var balance [10] float32
    

    初始化数组

    以下演示了数组初始化:

    var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    

    初始化数组中 {} 中的元素个数不能大于 [] 中的数字。

    如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:

     var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    

    该实例与上面的实例是一样的,虽然没有设置数组的大小。

    balance[4] = 50.0
    

    以上实例读取了第五个元素。数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为 0,第二个索引为 1,以此类推。

    访问数组元素

    数组元素可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值。例如:

    var salary float32 = balance[9]
    

    以上实例读取了数组balance第10个元素的值。

    以下演示了数组完整操作(声明、赋值、访问)的实例:

    package main
    
    import "fmt"
    
    func main() {
       var n [10]int /* n 是一个长度为 10 的数组 */
       var i,j int
    
       /* 为数组 n 初始化元素 */        
       for i = 0; i < 10; i++ {
          n[i] = i + 100 /* 设置元素为 i + 100 */
       }
    
       /* 输出每个数组元素的值 */
       for j = 0; j < 10; j++ {
          fmt.Printf("Element[%d] = %d
    ", j, n[j] )
       }
    }
    

     以上实例执行结果如下:

    Element[0] = 100
    Element[1] = 101
    Element[2] = 102
    Element[3] = 103
    Element[4] = 104
    Element[5] = 105
    Element[6] = 106
    Element[7] = 107
    Element[8] = 108
    Element[9] = 109

    数组初始化
    
    初始化数组的初始化有多种形式。
    
    [5] int {1,2,3,4,5}
    
    长度为5的数组,其元素值依次为:1,2,3,4,5。
    
    [5] int {1,2}
    
    长度为 5 的数组,其元素值依次为:1,2,0,0,0 。
    
    在初始化时没有指定初值的元素将会赋值为其元素类型 int 的默认值0,string 的默认值是 ""。
    
    [...] int {1,2,3,4,5}
    
    长度为 5 的数组,其长度是根据初始化时指定的元素个数决定的。
    
    [5] int { 2:1,3:2,4:3}
    
    长度为 5 的数组,key:value,其元素值依次为:0,0,1,2,3。在初始化时指定了 2,3,4 索引中对应的值:1,2,3
    
    [...] int {2:1,4:3}
    
    长度为5的数组,起元素值依次为:0,0,1,0,3。由于指定了最大索引 4 对应的值 3,根据初始化的元素个 数确定其长度为5赋值与使用。
    
    切片的初始化
    
    切片可以通过数组来初始化,也可以通过内置函数 make() 初始化。
    
    初始化时 len=cap,在追加元素时如果容量 cap 不足时将按 len 的 2 倍扩容。
    
    s :=[] int {1,2,3 } 直接初始化切片,[] 表示是切片类型,{1,2,3} 初始化值依次是 1,2,3。其 cap=len=3。
    
    s := arr[:] 初始化切片 s,是数组 arr 的引用。
    
    s := arr[startIndex:endIndex] 将 arr 中从下标 startIndex 到 endIndex-1 下的元素创建为一个新的切片。
    
    s := arr[startIndex:] 缺省 endIndex 时将表示一直到 arr 的最后一个元素。
    
    s := arr[:endIndex] 缺省 startIndex 时将表示从 arr 的第一个元素开始。
    
    s1 := s[startIndex:endIndex] 通过切片 s 初始化切片 s1
    
    s :=make([]int,len,cap) 通过内置函数 make() 初始化切片 s,[]int 标识为其元素类型为 int 的切片。
    
     

    复习代码

    package main
    
    import "fmt"
    
    
    //该函数接受一个数组作为参数,在函数中修改数组,不会对函数外面的数组产生影响
    func func_test4_1(a [5] int)  {
    	a[0] = 1000
    	fmt.Println(a)
    }
    
    //该函数接受一个数组指针作为参数,在函数中修改数组,会对函数外面的数据产生影响
    func func_test4_2(a * [5] int)  {
    	a[0] = 1000
    	fmt.Println(a)
    }
    
    
    func main()  {
    	var test4_1 [5] int
    	fmt.Println(test4_1)
    
    
    
    	test4_2 := [5] int {0,1,2,3,4}
    	fmt.Println(test4_2,len(test4_2),cap(test4_2))
    
    
    	test4_3 := [...] int {0,1,2,3,4}
    	fmt.Println(test4_3,len(test4_3),cap(test4_3))
    
    	for k := 0;k < len(test4_3);k ++ {
    		fmt.Println(test4_3[k])
    	}
    
    
    	//如果有两个参数接受,那么这里的k是索引,v是指
    	for k,v := range test4_3 {
    		fmt.Println(k,v)
    	}
    
    	//如果有一个参数接受,那么这个参数就是k
    	for k:= range test4_3 {
    		fmt.Println(k)
    	}
    
    	fmt.Println(test4_3)
    	//[0 1 2 3 4]
    	func_test4_1(test4_3)
    	//[1000 1 2 3 4]
    	fmt.Println(test4_3)
    	//[0 1 2 3 4]
    
    
    	func_test4_2(&test4_3)
    	//&[1000 1 2 3 4]
    	fmt.Println(test4_3)
    	//[1000 1 2 3 4]
    }
    
  • 相关阅读:
    Linux-RedHat 手动创建RAID和LVM分区
    Centos 文件系统 xfs、ext4、ext3 的区别
    CentOS7.5 rpm方式安装MySQL8.0.13
    virtualbox-host-only模式主机能上网虚拟机无法上网的问题解决
    RPA-智能流程自动化解决方案
    论文笔记——Rethinking the Inception Architecture for Computer Vision
    论文笔记——Factorized Convolutional Neural Networks
    论文笔记—Flattened convolution neural networks for feedforward acceleration
    论文笔记——Data-free Parameter Pruning for Deep Neural Networks
    AlexNet网络结构特点总结
  • 原文地址:https://www.cnblogs.com/bainianminguo/p/10854386.html
Copyright © 2011-2022 走看看