首页 > 其他分享 >Go 语言数组和切片的区别

Go 语言数组和切片的区别

时间:2023-04-02 12:15:03浏览次数:55  
标签:int fmt 切片 Println numbers 数组 Go

原文链接: Go 语言数组和切片的区别

在 Go 语言中,数组和切片看起来很像,但其实它们又有很多的不同之处,这篇文章就来说说它们到底有哪些不同。

另外,这个问题在面试中也经常会被问到,属于入门级题目,看过文章之后,相信你会有一个很好的答案。

数组

数组是同一种数据类型元素的集合,数组在定义时需要指定长度和元素类型。

例如:[4]int 表示一个包含四个整数的数组,数组的大小是固定的。并且长度是其类型的一部分([4]int[5]int 是不同的、不兼容的类型)。

数组元素可以通过索引来访问,比如表达式 s[n] 表示访问第 n 个元素,索引从零开始。

声明以及初始化

func main() {
    var nums [3]int   // 声明并初始化为默认零值
    var nums1 = [4]int{1, 2, 3, 4}  // 声明同时初始化
    var nums2 = [...]int{1, 2, 3, 4, 5} // ...可以表示后面初始化值的长度
    fmt.Println(nums)    // [0 0 0]
    fmt.Println(nums1)   // [1 2 3 4]
    fmt.Println(nums2)   // [1 2 3 4 5]
}

函数参数

如果数组作为函数的参数,那么实际传递的是一份数组的拷贝,而不是数组的指针。这也就意味着,在函数中修改数组的元素是不会影响到原始数组的。

package main

import (
    "fmt"
)

func Add(numbers [5]int) {
    for i := 0; i < len(numbers); i++ {
        numbers[i] = numbers[i] + 1
    }
    fmt.Println("numbers in Add:", numbers) // [2 3 4 5 6]
}

func main() {
    // declare and initialize the array
    var numbers [5]int
    for i := 0; i < len(numbers); i++ {
        numbers[i] = i + 1
    }

    Add(numbers)
    fmt.Println("numbers in main:", numbers) // [1 2 3 4 5]
}

切片

数组的使用场景相对有限,切片才更加常用。

切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。

切片是一种引用类型,它有三个属性:指针长度容量

  1. 指针:指向 slice 可以访问到的第一个元素。
  2. 长度:slice 中元素个数。
  3. 容量:slice 起始元素到底层数组最后一个元素间的元素个数。

底层源码定义如下:

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

声明以及初始化

func main() {
    var nums []int  // 声明切片
    fmt.Println(len(nums), cap(nums)) // 0 0
    nums = append(nums, 1)   // 初始化
    fmt.Println(len(nums), cap(nums)) // 1 1

    nums1 := []int{1,2,3,4}    // 声明并初始化
    fmt.Println(len(nums1), cap(nums1))    // 4 4

    nums2 := make([]int,3,5)   // 使用make()函数构造切片
    fmt.Println(len(nums2), cap(nums2))    // 3 5
}

函数参数

当切片作为函数参数时,和数组是不同的,如果一个函数接受一个切片参数,它对切片元素所做的更改将对调用者可见,类似于将指针传递给了底层数组。

package main

import (
    "fmt"
)

func Add(numbers []int) {
    for i := 0; i < len(numbers); i++ {
        numbers[i] = numbers[i] + 1
    }
    fmt.Println("numbers in Add:", numbers) // [2 3 4 5 6]
}

func main() {
    var numbers []int
    for i := 0; i < 5; i++ {
        numbers = append(numbers, i+1)
    }

    Add(numbers)

    fmt.Println("numbers in main:", numbers) // [2 3 4 5 6]
}

再看一下上面的例子,把参数由数组变成切片,Add 函数中的修改会影响到 main 函数。

总结

最后来总结一下,面试时也可以这么来回答:

  1. 数组是一个长度固定的数据类型,其长度在定义时就已经确定,不能动态改变;切片是一个长度可变的数据类型,其长度在定义时可以为空,也可以指定一个初始长度。
  2. 数组的内存空间是在定义时分配的,其大小是固定的;切片的内存空间是在运行时动态分配的,其大小是可变的。
  3. 当数组作为函数参数时,函数操作的是数组的一个副本,不会影响原始数组;当切片作为函数参数时,函数操作的是切片的引用,会影响原始切片。
  4. 切片还有容量的概念,它指的是分配的内存空间。

以上就是本文的全部内容,如果觉得还不错的话欢迎点赞转发关注,感谢支持。


参考文章:

推荐阅读:

标签:int,fmt,切片,Println,numbers,数组,Go
From: https://www.cnblogs.com/alwaysbeta/p/17280205.html

相关文章

  • 453.最小操作次数使数组元素相等
    最小操作次数使数组元素相等给你一个长度为n的整数数组,每次操作将会使n-1个元素增加1。返回让数组所有元素相等的最小操作次数。示例1:输入:nums=[1,2,3]输出:3解释:只需要3次操作(注意每次操作会增加两个元素的值):[1,2,3]=>[2,3,3]=>[3,4,3]=>[4,4,4]......
  • django直线支付宝支付接口
    1.创建Django项目首先,在命令行中使用以下命令创建一个新的Django项目:django-adminstartprojectproject_name2.安装PythonSDK然后,下载并安装支付宝PythonSDK。可以使用pip命令进行安装:pipinstallalipay-sdk-python3.配置支付宝参数配置支付宝参数在settings.py文件......
  • Go语言入门2(流程控制,string)
    流程控制选择结构(分支语句)​ 因为switch只能匹配固定值,推荐使用if-else做条件筛选if-else判断packagemainimport"fmt"funcmain(){ vartmpAint fmt.Scanln(&tmpA) iftmpA>=90{ fmt.Println("tmpA>=90") }elseiftmpA<90&&tmpA>......
  • 1438. 绝对差不超过限制的最长连续子数组
    力扣题目链接给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。如果不存在满足条件的子数组,则返回 0 。 示例1:输入:nums=[8,2,4,7],limit=4输出:2解释:所有子数组......
  • [LeetCode] 1338. Reduce Array Size to The Half 数组大小减半
    Youaregivenanintegerarray arr.Youcanchooseasetofintegersandremovealltheoccurrencesoftheseintegersinthearray.Return theminimumsizeofthesetsothat atleast halfoftheintegersofthearrayareremoved.Example1:Input:arr=......
  • Django笔记十三之select_for_update等选择和更新等相关操作
    本篇笔记将介绍update和create的一些其他用法,目录如下:get_or_createupdate_or_createselect_for_updatebulk_createbulk_update1、get_or_create前面我们介绍过get()和create()的用法,那么get_or_create()的意思很简单,就是获取或者创建,如果存在就返回,不存在就......
  • MongoDB 架构
    优质博文:IT-BLOG-CN一、存储数据格式MongoDB作为主流的NoSQL数据库之一,使用面向文档的数据存储方式,将数据以JSON和BSON的方式存储在磁盘中。BSONBinaryJSON是一种基于JSON的二级制序列化格式,用于MongoDB存储文档并进行远程过程调用,作为网络数据交互的一种存储形式,类似于Prot......
  • golang蒙特卡洛树算法实现五子棋AI
    已经实现蒙特卡洛树算法的通用逻辑,只需要对应结构体实现相关接口就可以直接使用该算法。优化算法主要优化GetActions生成下一步动作,要尽可能少,去掉无意义的动作。以及优化ActionPolicy从众多动作挑选比较优秀的动作。对应五子棋就是执行该动作后当前局面评分最高。packagemain......
  • django 中model 的序列换
    方法一:from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize("json",ret) 方法二:当只有一个object时:fromdjango.forms.modelsimportmodel_to_dictdata=model_to_dict(yourmodelobject)......
  • 【入门】Go语言排序算法详解
    1、冒泡排序冒泡排序是一种简单的排序算法,它重复地遍历要排序的列表,比较相邻的两个元素,并在必要时交换它们的位置,直到没有任何一对元素需要交换为止。该算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。packagemainimport"fmt"//我们定义了一个名为`bu......