初始化:数组需要指定大小,不指定也会根据初始化的自动推算出大小,不可改变

数组:

a := [...]int{,,}
a := []int{,,}

切片:

a:= []int{,,}
a := make([]int, )
a := make([]int, , )
slice的数据结构:

go源码slice的数据结构定义:

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

一个指向真实 array 地址的指针 ptr ,slice 的长度 len 和容量 cap

函数传递:数组需要明确指定大小,切片不需要。数组是值传递,切片是地址传递
numbers2 := [...]int{, , , , , }
maxIndex2 := len(numbers2) -
for i, e := range numbers2 {
if i == maxIndex2 {
numbers2[] += e
} else {
numbers2[i+] += e
}
}
fmt.Println(numbers2) numbers3 := []int{, , , , , }
maxIndex3 := len(numbers3) -
for i, e := range numbers3 {
if i == maxIndex3 {
numbers3[] += e
} else {
numbers3[i+] += e
}
}
fmt.Println(numbers3)

输出:

[     ]
[ ]

观察slice append的时候内存地址会不会改变:

通过一个例子:

package main

import (
"fmt"
"unsafe"
) func main() {
//说先定义一个切片,只限定长度为1
s := make([]int, 1) //打印出slice的长度,容量以及内存地址
fmt.Printf("len :%d cap:%d array ptr :%v \n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s))) for i := 0; i < 5; i++ {
s = append(s, i)
fmt.Printf("len :%d cap:%d array ptr :%v \n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s)))
}
//打印出slice
fmt.Println("array:", s)
}

输出:

len : cap: array ptr :0xc042062080
len : cap: array ptr :0xc0420620c0
len : cap: array ptr :0xc0420600e0
len : cap: array ptr :0xc0420600e0
len : cap: array ptr :0xc0420880c0
len : cap: array ptr :0xc0420880c0
array: [ ]

可以看出来在append的过程中,内存地址有些是一样的,有些是不一样的,容量也是如此

看出来了吧,每次cap改变的时候指向array内存的指针都在变化。当在使用 append 的时候,如果 cap==len 了这个时候就会新开辟一块更大内存,然后把之前的数据复制过去。

  1. 而cap是以乘以2的速度扩展的。这里是不是真的就是乘以2的速度呢??
  2. 最后一句输出slice元素的时候为什么会多了一个0呢??

对于问题2:是因为make初始化时,都会初始化成对应数据类型的原值

我们再来测试一下问题1:

package main

import (
"fmt"
"unsafe"
) func main() {
//说先定义一个切片,只限定长度为1
s := make([]int, ) //打印出slice的长度,容量以及内存地址
fmt.Printf("len :%d cap:%d array ptr :%v \n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s))) for i := ; i < *; i++ {
s = append(s, i)
fmt.Printf("len :%d cap:%d array ptr :%v \n", len(s), cap(s), *(*unsafe.Pointer)(unsafe.Pointer(&s)))
}
//打印出slice
fmt.Println("array:", s)
}

输出太多了,就截一部分:

如果按照上面得出的结论,那cap为1024的下一个应该是2048,但是却是1280

实际go在append的时候放大cap是有规律的。在 cap 小于1024的情况下是每次扩大到  * cap ,当大于1024之后就每次扩大到 1.25 * cap 。

golang中数组与切片的区别的更多相关文章

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

    数组 Arrays 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值.在初始化后长度是固定的,无法修改其长度.当作为方法的入参传入时将复制一份数 ...

  2. Golang数组和切片的区别

    大纲 数组是固定大小 切片不是动态数组,可以扩容 区别 定义方式不一样 初始化方法不一样 package main import "fmt" func main() { // -- ...

  3. golang中数组指针与指针数组的区别实现

      指针数组和数组的指针,指的是两个不同的东西. 指针数组是有指针组成的数组,数组的指针是一个数组的指针. package main import "fmt" const MAX ...

  4. Go数组和切片你不知道的区别

    开篇语 数组和切片是两种不同的数据结构,比较常见,在Go语言中同时存在,今天我们就一起来看看他们在使用方式上,原理上的一些区别? 数组 在Go语言中,数组是一种具有相同类型固定大小的一种数据结构. 我 ...

  5. golang笔记——数组与切片

    一.切片的定义 我们可以从数组(go语言中很少直接使用数组)或者切片来初始化一个新的切片,也可以直接通过 make 来初始化一个所有元素为默认零值的切片. //1.通过数组来初始化切片 arr := ...

  6. [Go] gocron源码阅读-go语言中数组和切片的字面值初始化语法

    源码中有这么一句,这个函数要求返回的是[]cli.Command,cli.Command类型的切片,这个地方直接使用字面值初始化了一个切片返回去了 return []cli.Command{comma ...

  7. golang之数组与切片

    数组 数组可以存放多个同一类型数据,数组也是一种数据类型,在Go中,数组是值类型. 数组的定义: var 数组名 [数组大小]数据类型 var a [5]int 赋初值   a[0] = 1    a ...

  8. 『GoLang』数组与切片

    数组 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列(这是一种同构的数据结构):这种类型可以是任意的原始类型例如整型.字符串或者自定义类型. 数组长度必须是一个常量表达式,并且必须是一个非负 ...

  9. c语言中数组的定义和java中数组定义的一些区别

    感谢原文:https://blog.csdn.net/gzwdz778/article/details/79799408 一维情况下: c中,数组的声明需要给出数组的维数,比如: int arr[5] ...

随机推荐

  1. Nginx实战-后端应用健康检查

    严格来说,nginx是没有针对负载均衡后端节点的健康检查的,但是可以通过proxy_next_upstream来间接实现,但这个还是会把请求转发给故障服务器的,然后再转发给别的服务器,这样就浪费了一次 ...

  2. #10 Python字符串

    前言 通过上一节可知,Python6个序列的内置类型中,最常见的是列表和元组,但在Python中,最常用的数据类型却不是列表和元组,而是字符串.要想深入了解字符串,必须先掌握字符编码问题.因此本篇博文 ...

  3. 【学习笔记】AJAX内容拓展

    题记——近期回顾<javaScript高级程序设计>ajax章节,发现书中对封装一个ajax库并不完美,结合之前看到博客,对ajax库做一点点的优化. 参考博客:如何去封装一个ajax库 ...

  4. ServerSocket和Socket

    前言 用ServerSocket和Socket做了个Server.Client通信的demo,以及学习下在这个demo过程中用到java.net.java.io包下几个常用的类. Server imp ...

  5. [转]angular2中ng alerts的使用教程

    本文转自:https://blog.csdn.net/m0_37981481/article/details/79281879 由于想要一个好看的alert,于是去npm上搜了一下,手动捂脸,npm上 ...

  6. 【ichart】简单的统计图表ichart.js的使用

    1.首先下载,点击下载 2.只需要这一个js,粘贴赋值到自己项目中即可.   3.引入js <script type="text/javascript" src=" ...

  7. Aspose.Cells API 中文版文档 下载

    链接: https://pan.baidu.com/s/19foJyWgPYvA7eIqEHJ_IdA 密码: yxun

  8. What are the differences between a pointer variable and a reference variable in C++?

    Question: I know references are syntactic sugar, so code is easier to read and write. But what are t ...

  9. 理解es6中的const与“不变”

    const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动. 效果 对于简单类型的数据(数值.字符串.布尔值),值就保存在变量指向的那个内存地址,因此等同于常量. 对于复合类型 ...

  10. Confluence设置MySQL数据库报错:必须使用'READ-COMMITTED'作为默认隔离级别。

    解决方案: mysql -u root -p123456 SET GLOBAL tx_isolation='READ-COMMITTED'; mysql数据库创建 1.设置mysql隔离级别 SET ...