Go 数组与切片

#### Go 数组与切片***渡风渡尘缘,修行亦修心***##### 数组数组是可以存放多个同一类型的数据的集合,数组也是一种数据类型,它是值类型;  数组如何定义?    var 数组名 [数组大小]数据类型: var a [5]int 
package main

import "fmt"

func main(){
   var intArr [3]int
   intArr[0] = 10
   intArr[1] = 20
   intArr[2] = 30
   fmt.Println(intArr)
}

  

数组在内存中的布局:  

1. 数组的地址可以通过数组名获取: &intArr;   2. 数组的第一个元素地址就是数组的地址:;  3. 数组的各个元素的地址间隔根据数组的类型决定: int64-> 8 字节,int32-> 4字节;  4. 数组如果未给元素赋值,元素的默认值为类型的零值: int64->0,string->"",float64->0;  5. 访问数组中的元素: 使用下标索引方式(左闭右开方式),这个与其它语言一样,超出下标索引将会出错,索引越界;6. 数组的遍历有两种方式: for 传统方式; for range 方式 ;    
package main

import "fmt"

func main(){
   var a [5]int
   a[0] = 1
   a[1] = 2
   a[2] = 3
   // 默认值: a[3] = 0 , a[4] = 0
   // 下标越界: a[5] = 10  // 错误, 下标越界
   fmt.Println(a) //[1 2 3 0 0 ]
   fmt.Printf("a address is %p\n",&a) // 0xc000078030
   fmt.Printf("a[0] address is %p\n",&a[0]) //0xc000078030
   fmt.Printf("a[1] address is %p\n",&a[1]) //0xc000078038
   fmt.Printf("a[2] address is %p\n",&a[2]) //0xc000078040
   // 数组的遍历方式
   for i:=0;i<len(a);i++{
      fmt.Println(a[i])
   }
   // for range 方式
   for k,v := range a {
      fmt.Println(a[k])
      fmt.Println(v)  // 这个值是元素的副本, 所以不建议在v 上操作: 取址或赋值;
   }
}

  

---数组有多种初始化方式:  
import "fmt"

func main(){
   // 1. 字面量直接赋值
   var a [5]int = [5]int{1,2,3,4,5}
   var b = [5]int{6,7,8,9,0}
   // 2. 数组长度由编译器推导
   var c = [...]int{1,2,3,4,5,6}
   // 3. 根据索引位置直接赋值
   var d = [...]int{1:1,10:0,3:3}
   // 4. 类型推导
   f := [...]int{1:1,9:9,10:0}
   fmt.Println(a)
   fmt.Println(b)
   fmt.Println(c)
   fmt.Println(d)
   fmt.Println(f)
}

  

---数组使用注意事项1. 数组是多个相同类型的集合,一旦声明或者定义了,数组的长度将是固定不变的,不能动态变化 ;  2. 数组中的元素可以是任意类型,可以是值类型,也可以是引用类型,不可以混用;  3. 数组创建后如果不赋值,将采用类型的零值 ;  4. 数组属于值类型, 在默认情况下是传递数组是值传递,所以数组之间不会影响;  5. 如果需要更改原数组,需要传递数组的地址(类似引用传递);  6. 长度是数组类型的一部分,在传递参数时需要注意数组的长度;  
package main

import "fmt"

func test01(a [5]int){
   a[1] = 20
   fmt.Println(a)  //[1 20 3 4 5]
}
func test02(a *[5]int){
   a[1] = 20
   fmt.Println(*a) // [1 20 3 4 5]
}
func main(){
   var a = [5]int{1,2,3,4,5}
   test01(a)
   fmt.Println(a) // [1 2 3 4 5]
   // 如果需要修改原数组的值,需要传递数组的地址
   test02(&a)
   fmt.Println(a) // [1 20 3 4 5]
   // 传递参数时需要考虑数组的长度
   //var b = [3]int{1,2,3}
   //test01(b) // 错误, 数组的长度不正确
}

  

在Go 编程中,数组的使用还是不太多, 因为不能动态的扩容,数组一般作为已经确定的数据使用;  ##### 切片1. 切片是数组的一个引用, 所以切片属于引用类型,在进行参数传递时,属于引用传递;  2. 切片的使用与数组类似: 遍历,访问等; 3. 切片的长度是可以动态变化的,所以也可以说切片是动态变化的数组;  4. 切片的基本语法 :var 切片名 []类型
package main

import "fmt"

func main(){
   // 这里只演示切片如何使用,稍后再介绍切片如何声明与赋值操作
   // 声明并定义一个数组
   var a = [5]int{1,2,3,4,5}
   // 切片s 引用已经存在的数组a
   var s = a[:] // 这种方式引用所有的数组元素,也可引用一部分数组元素 var s = a[1:3]
   fmt.Printf("%T\n",s)
   fmt.Println(s)
   fmt.Println(len(s)) // 5 切片的长度
   fmt.Println(cap(s)) // 5 切片的容量,容量和长度是可以动态变化;
}

  

--- 切片在内存中的布局

1. slice 是一下引用类型; 2. 从底层上讲,slice 实际上就是一个结构体(稍后会学习到)type slice struct {      ptr *[2]int      len   int       cap   int  }切片的初始化 
package main

import "fmt"

func main(){
   // 方式1 创建一个数组,让切片引用这个数组
   var a = [5]int{1,2,3,4,5}
   var s = a[:]
   // 同数组一样, 在赋值或取值时,仍然需要注意切片下标索引不可越界
   //s[10] = 0
   s[4] = 50
   fmt.Println(s)
   // 方式2
   // 切片是引用类型,所以声明后需要make 分配内存
   var b []int
   // make 分配内存,长度可以指定任意值,建议根据要存储的数据长度合适定义
   // make 参数,还可以定义切片的容量,如果定义了切片的容量,则要求容量大于切片的长度
   b = make([]int,5)
   fmt.Println(b)
   // 方式3
   // 字面量方式,声明后直接赋值
   var c = []int{1,2,3,4,5}
   fmt.Println(c)
}

  

1. 方式1: 直接引用已经存在的数组,开发者对底层是可见的;  2. 方式2: 通过make 创建的切片,程序也会创建一个数组,不过这个数组对开发者不可见,由程序自己维护;  3. 方式3: 类似make;   ---切片使用的注意事项:  1. 切片的遍历与访问同数组一样, 这里就不写了;  2. 切片定义后,不能直接使用,需要引用一个数组或make 分配内存给切片使用;  3. 使用append 函数可以对切片进行动态扩容;  4. 使用copy 函数可以对切片进行拷贝,拷贝后的切片是独立的, 在新的切片上操作对原切片没有影响;  5. 切片是引用类型,在给函数传递参数(切片)时,属于引用传递;  
package main

import "fmt"

func test01(a []int){
   a[0] = 100
   fmt.Println(a)
}
func main(){
   var a = []int{1,2,3}
   fmt.Println(a)
   // 使用append 函数将切片扩容
   a = append(a,4)
   fmt.Println(a)
   // 使用copy 函数进行切片复制
   // 在使用copy 函数时需要注意以下几点:
   //1. 目标(dst)必须是已经声明并初始化过的
   //2. 如果目标的长度小于被复制的切片长度,则以目标的长度为准复制,超出部分不复制;
   var b []int
   b = make([]int,3)// 超出元素4,将不会被复制
   copy(b,a)
   fmt.Println(b)
   // 对新切片的操作不会影响到原来的切片
   b[1] = 10
   fmt.Println(a)
   fmt.Println(b)
   // 切片属于引用传递
   test01(a)
   fmt.Println(a)
}

  

--- string 与slice 在学习基本数据类型时我们学习了string 类型,知道它是由多个字节连接在一起的字符串;  实际上string 底层是一个字节数组,所以string 也可以进行切片操作;  但是string 是不可变的, 所以不能string[0]=‘x‘, 这种赋值操作; 如果需要更改,需要将string 转为[]byte 切片,更改完成后再转为string 类型;  
package main

import "fmt"

func main(){
   var a = "abcdef"
   // 可以进行切片处理
   fmt.Println(a[:3])
   // 不可以更改string 的值
   // a[1] = ‘f‘ //这是错误的
   // 需要将string 转为 []byte 切片才可以操作
   var arr []byte
   arr = []byte(a)
   arr[1] = ‘f‘
   a = string(arr) // 更改完成后再将切片转为string 类型
   fmt.Println(a)
   // []byte 只能处理英文与数字,处理其它语言时需要将string 转为[]rune 切片
   var b = "你好啊"
   var arr2 []rune
   arr2 = []rune(b)
   arr2[0] = ‘我‘
   b = string(arr2)
   fmt.Println(b)
}

  个人微信公众号上有最新的文章,欢迎大家关注,一同交流学习

原文地址:https://www.cnblogs.com/Mail-maomao/p/11411807.html

时间: 2024-08-05 04:56:19

Go 数组与切片的相关文章

GoLang笔记-数组和切片,本质是就是长度不可变的可变的区别

数组 Arrays 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值.在初始化后长度是固定的,无法修改其长度.当作为方法的入参传入时将复制一份数组而不是引用同一指针.数组的长度也是其类型的一部分,通过内置函数len(array)获取其长度. 初始化 数组的初始化有多种形式,查看示例代码 , 在线运行示例代码 [5] int {1,2,3,4,5} 长度为5的数组,其元素值依次为:1,2,3,4,5 [5] int {1,2} 长度为5的数组

GO语言总结(3)——数组和切片

上篇博文简单介绍了一下Go语言的基本类型——GO语言总结(2)——基本类型,本篇博文开始介绍Go语言的数组和切片. 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建. 数组有3种创建方式:[length]Type .[N]Type{value1, value2, ... , valueN}.[...]Type{value1, value2, ... , valueN} 如下: func test5() { var iarray1 [5]int32

go的数组和切片

对于GO的数组和切片的初步了解, 切边是数组的一个指针,切片的初始化有三种:一种是通过make,即 slice := make([]int,5,10) 另一种是通过:=指向一个已经存在的数组.即 slice := []int {1,2,3,4,5,6} 切片的切片不可初始化超过原始切片的cap值,比如: sliceA := make([]int,5,10) sliceB := sliceA[:11] 这个是不行的,11超过了sliceA的cap值(10),会报运行时异常. 对切片的append,

Go - 数组 和 切片

一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建 数组有 3 种创建方式: 1) [length]Type 2) [length]Type{value1, value2, ... , valueN} 3) [...]Type{value1, value2, ... , valueN} 如下: func test5() { var arr1 [5]int32 var arr2 [5]int32 = [5]int32{1, 2, 3, 4, 5} a

Go数组、切片、映射的原理--简明解析

数组.切片.映射是Golang的最重要的数据结构,下面是对这3种数据结构的一点个人总结: 一.数组 数组是切片和映射的基础数据结构. 数组是一个长度固定的数据类型,存储着一段具有相同数据类型元素的连续内存块. 因为数组占用的内存是连续分配的,所以对数组的操作速度很快. 声明数组的方式:4种 var array1 [5]int array1 := [5]int{3,5,6,3,2} array1 := [...]int{3,4,7,8,1} //根据数组字面量中元素的个数来确定数组的长度 arra

GO的数组及切片

感觉在向PYTHON学一些数组方面的功能. package main import "fmt" func main() { var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} var mySlice []int = myArray[:5] fmt.Println("Elements of myArray: ") for _, v := range myArray { fmt.Print(v, &q

python运算学习之Numpy ------ 数组的切片索引与循环遍历、条件和布尔数组、

数组的切片索引: 数组的切片索引和列表非常类似,下面用代码简单说明 1 a = np.random.rand(16).reshape(4, 4) 2 print("数组a:\n", a) 3 print(a[-1][1:4]) 4 Out[1]: 5 数组a: 6 [[0.04175379 0.43013992 0.5398909 0.40638248] 7 [0.3305902 0.11958799 0.48680358 0.30755734] 8 [0.00893887 0.384

go 语言学习 - 数组和切片

package main import "fmt" func main(){ //数组 var a = [3]int{}//相当于[3]int{0,0,0} a[0] = 1 changeArray(a) fmt.Println(a) b := [...]int{1,2,3}//省略号符号表示让编译器根据后面初始化情况自动计算数组的长度,但这个长度是编译时确定的 fmt.Println(b) c := new([3]int) //new 返回的是地址,但是一样可以用 pointName

Go语言入门——数组、切片和映射

按照以往开一些专题的风格,第一篇一般都是“从HelloWorld开始” 但是对于Go,思来想去,感觉真的从“HelloWorld”说起,压根撑不住一篇的篇幅,因为Go的HelloWorld太简单了. 1.简介 Go是什么? Go(又称Golang)是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回收功能的编程语言.——摘自百度百科 Github地址 https://github.com/golang/go 官网地址 https://golang.org 中文网社区 https://

数组和切片

实际上就是个数组.底层是一个数组,切片内有这个数组引用,和切片的信息.var arrAge = [5]int{18, 20, 15, 22, 16}var arrLazy = [...]int{5, 6, 7, 8, 22}//...可以忽略var arrKeyValue = [5]string{3: "Chris", 4: "Ron"}切片; x.y是切片改变x.y就是改变数组,向x.y添加数据也是改变数组. make创建一个切片:make([]int,len,c