第七章 Golang数组和切片

简介: 第七章 Golang数组和切片

数组的使用注意事项和细节

1.数组是多个相同类型数据的结合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化。

2.var arr []int 这时arr就是一个slice切片,切片后面专门讲解。

3. 数组中的元素可以是任何数据类型,包括值类型和引用类型,但是不能混用。

4. 数组创建后,如果没有赋值,有默认值(零值)

数值类型数组:默认值为0

字符串数组:默认值为“”

bool数组:默认值为false

5. 使用数组的步骤 a.声明数组并开辟空间 b.给数组各个元素赋值(默认零值)c.使用数组

6. 数组的下标是从0开始的。

7. 数组下班必须在指定范围内使用,否则报panic:数组越界,比如var arr [5]int 则有效下表为0-4

8. Go的数组属值类型:在默认情况下是值传递,因此会进行拷贝。数组间不会相互影响

9. 如想在其他函数中,去修改原来的数组,可以使用应用传递(指针方式)

10.长度是数组类型的一部分,在传递函数参数时 需要考虑数组的长度,看下面案例

要求:生成五个数,并将其反转打印

// 思路 1.生成五个数,rand.Intn()函数  2.当我们得到随机数后,就放到一个数组 int数组 3.反转打印,交换的次数是len/2,倒数第一个和第一个元素交换,倒数第二个和第二个交换
var intArr3 [5]int
len := len(intArr3)
rand.Seed(time.Now().UnixNano())
for i := 0;i<len;i++ {
  intArr3[i] = rand.Intn(100) 
}
fmt.Println("交换前=",intArr3)
temp := 0
for i:=0;i<len/2;i++{
  temp = intArr3[len-1-i]
  intArr3[len-1-i] = intArr3[i]
  intArr3[i] = temp
}
fmt.Println("交换后=",intArr3)

为什么需要切片

先来看一个需求,我们需要一个数组用于保存学生的成绩,但是学生的个数是不确定的,请问怎么办:解决方案使用**切片**

切片的基本介绍

  1. 切片的英文是slice
  2. 切片是数组的一个引用,因此切片是引用类型,在精选传递时,遵循引用传参的机制
  3. 切片的使用和数组类似,遍历切片,访问切片的元素和求切片长度len(slice)都一样。
  4. 切片的长度是可以变化的,因此切片是一个可以动态变化的数组
  5. 切片定义的基本语法:
    var 切片名 []类型
    比如:var a [] int

切片快速入门

package main
import (
  "fmt"
)
func main(){
  // 演示切片的基本使用
  var intArr [5]int = [...]int{1,22,33,55,99}
  // 声明/定义一个切片
  // slice := intArr[1:3]
  // l.slice 就是切片名
  // 2.intArr[1:3]表示slice引用到intArr这个数组
  // 3.引用intArr数组的起始下标为1,最后的下标为3(但是不包含3)
  slice := intArr[1:3]
  fmt.Println("intArr=",intArr)
  fmt.Println("slice 的元素是 =",slice) // 22,33
  fmt.Println("slice 的元素个数 =",len(slice)) //2
  fmt.Println("slice 的容量 =",cap(slice)) // 切片的容量是可以动态变化
}

切片在内存中形式

基本介绍

为了让大家更加深入的理解切片,我们画图分析一下切片在内存中是如何布局的,这是一个非常重要的知识点

画出前面的内存分布图

对上面的分析总结

1.slice的确是一个引用类型

2.slice 从底层来说,其实就是一个数据结构(struct结构体)

type slice struct{
ptr *[2]int
len int
cap int
}

切片的使用

方式一:定义一个切片,然后让切片去引用一个定义好的数组,比如之前的案例就是这样的。

方式二:通过make来创建切片

基本语法:var 切片名 []type = make([]type,len,[cap])

参数说明:type:就是数据类型 len:大小 cap:指定切片的容量,可选,如果你分配了cap,则要求cap>=len

方式三:定义一个切片,直接就指定具体数组,使用原理类似make的方式

var strSlice []string = []string{"tom","jack","mary"}
fmt.Println("strSlice=",strSlice)
fmt.Println("strSlice size =",len(strSlice))
fmt.Println("strSlice cap =",cap(strSlice))

方式1和方式2的区别

方式1是直接引用数组,这个数组是事先存在的,程序员是可见的。方式2是通过make来创建切片,make也会创建一个数组,是由切片在底层进行维护,程序员是看不见的。

切片的遍历

切片的遍历和数组一样,也有两种方式

package main
import (
  "fmt"
)
func main(){
  // 使用常规的for循环遍历切片
  var arr [5]int = [...]int{10,20,30,40,50}
  slice  := arr[1:4] // 20,30,40
  for i := 0;i<len(slice);i++{
      fmt.Printf("slice[%v]=%v",i,slice[i])
  }
    // 使用for---range方式遍历切片
    for i,v := range slice{
      fmt.Printf("i=%v v=%v \n",i,v)
    }
}

切片注意事项和细节说明

用append内置函数,可以对切片进行动态追加

切片append操作的底层原理分析

  1. 切片append操作的本质就是对数组扩容
  2. go底层会创建一下新的数组newArr(安装扩容后大小)
  3. 将slice原来包含的元素拷贝到新的数组newArr
  4. slice重新引入到newArr
  5. 注意newArr是在底层来维护的,程序员不可见
  6. 切片是引用类型,所以在传递时,遵循引用传递机制。

切片的拷贝操作

切片使用copy内置函数完成拷贝,举例说明

func main(){
   var a []int = []int {1,2,3,4,5}
   var slice = make([]int,10)
   fmt.Println(slice)
   copy(slice,a)
   fmt.Println(slice)
}

string和slice

1.string底层是一个byte数组,因此string也可以进行切片处理

2.string和切片在内存的形式,以“abcd”画出内存示意图

3.string是不可变的,也就是说不能通过str[0]=‘z’方式来修改字符串

4. 如果需要修改字符串,可以先将string->[]byte/或者 []rune->修改->重写转成string.

切片生成斐波那契数列

func fbn(n int) ([]uint64){
  // 声明一个切片,切片大小n
  fbnSlice := make([]uint64,n)
  // 第一个数和第二个数的斐波那契 为1
  fbnSlice[0] = 1
  fbnSlice[1] = 1
  // 进行for循环来存放斐波那契的数列
  for i := 2;i<n;i++{
    fbnSlice[i] = fbnSlice[i-1] + fbnSlice[i-2]
  }
  return fbnSlice
}

感谢大家观看,我们下次见

目录
相关文章
|
3月前
|
Go
Golang语言之切片(slice)快速入门篇
这篇文章是关于Go语言中切片(slice)的快速入门教程,详细介绍了切片的概念、定义方式、遍历、扩容机制、使用注意事项以及相关练习题。
40 5
|
3月前
|
Go
Golang语言之数组(array)快速入门篇
这篇文章是关于Go语言中数组的详细教程,包括数组的定义、遍历、注意事项、多维数组的使用以及相关练习题。
52 5
|
4月前
|
监控 Serverless Go
Golang 开发函数计算问题之Go 语言中切片扩容时需要拷贝原数组中的数据如何解决
Golang 开发函数计算问题之Go 语言中切片扩容时需要拷贝原数组中的数据如何解决
|
6月前
|
Go
【golang】golang 字符串切片排序
【golang】golang 字符串切片排序
72 1
|
7月前
|
Go 索引
Golang深入浅出之-切片(Slices)入门:创建、操作与扩容机制
【4月更文挑战第20天】Go语言中的切片是动态数组,提供灵活的操作和自动扩容。本文介绍了切片的创建(通过`make()`、数组创建和切片字面量)、基本操作(索引访问、切片、赋值追加和遍历)以及扩容机制(首次和后续扩容策略)。此外,还强调了切片与底层数组的关系、切片越界问题、`append()`的使用以及理解切片的关键点,帮助提升Go编程效率和代码质量。
181 0
|
7月前
|
Java Go C++
Golang每日一练(leetDay0114) 矩阵中的最长递增路径、按要求补齐数组
Golang每日一练(leetDay0114) 矩阵中的最长递增路径、按要求补齐数组
70 0
Golang每日一练(leetDay0114) 矩阵中的最长递增路径、按要求补齐数组
|
7月前
|
Java Go C++
Golang每日一练(leetDay0088) 数组的乘积、搜索二维矩阵II
Golang每日一练(leetDay0088) 数组的乘积、搜索二维矩阵II
43 0
Golang每日一练(leetDay0088) 数组的乘积、搜索二维矩阵II
|
7月前
|
Java Go C++
Golang每日一练(leetDay0081) 基本计算器I\II Basic Calculator
Golang每日一练(leetDay0081) 基本计算器I\II Basic Calculator
59 0
Golang每日一练(leetDay0081) 基本计算器I\II Basic Calculator
|
7月前
|
算法 C++ Python
Golang每日一练(leetDay0052) 寻找旋转排序数组中的最小值I\II
Golang每日一练(leetDay0052) 寻找旋转排序数组中的最小值I\II
62 0
Golang每日一练(leetDay0052) 寻找旋转排序数组中的最小值I\II
|
7月前
|
C++ Python Go
Golang每日一练(leetDay0051) 颠倒字符串里的单词I\II、乘积最大子数组
Golang每日一练(leetDay0051) 颠倒字符串里的单词I\II、乘积最大子数组
61 0
Golang每日一练(leetDay0051) 颠倒字符串里的单词I\II、乘积最大子数组