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

数组:

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. Eureka自我保护模式——难点重点

    一.开启Eureka自我保护模式访问Eureka主页时,如果看到这样一段大红色的句子: EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ...

  2. Haproxy+Heartbeat 高可用集群方案操作记录

    之前详细介绍了haproxy的基础知识点, 下面记录下Haproxy+Heartbeat高可用web集群方案实现过程, 以加深理解. 架构草图如下: 1) 基本环境准备 (centos6.9系统) 1 ...

  3. JavaWeb学习 (二十八)————文件上传和下载

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  4. 【Spring】详解spring事务属性

    Spring声明式事务让我们从复杂的事务处理中得到解脱.使得我们再也无需要去处理获得连接.关闭连接.事务提交和回滚等这些操作.再也无需要我们在与事务相关的方法中处理大量的try…catch…final ...

  5. JAVA对Excel的导入导出

    今天需要对比2个excel表的内容找出相同:由于要学的还很多上手很慢所以在这做个分享希望对初学的有帮助: 先是pom的配置: <dependency> <groupId>org ...

  6. springboot整合freemarker----一点小小的错误

    最近小弟正在学习springboot,没办法,现在微服务太火了.小弟也要顺应时代的潮流啊 :( 好了,废话不多说了!!!! 首先在springboot的pom.xml添加freemarker的依赖 & ...

  7. CSS水平居中的三种方法

    CSS中经常会用到元素居中,那么今天我为大家分享几种水平居中的方法,下面代码都可以达到同样的居中效果,来不及解释了,快上马(码): 一.margin : 0 auto; <head> &l ...

  8. python自动化开发-6

    python的常用模块(续) shutil模块:主要是做文件复制的.文件,文件夹,压缩包等的处理模块. 常用的方法: shutil.copyfileobj:将文件的内容拷贝到另一个文件中. 例子: # ...

  9. 惊闻企业Web应用生成平台 活字格 V4.0 免费了,不单可视化设计器免费,服务器也免费!

    官网消息: 针对活字格开发者,新版本完全免费!您可下载活字格 Web 应用生成平台 V4.0 Updated 1,方便的创建各类 Web 应用系统,任意部署,永不过期. 我之前学习过活字格,也曾经向用 ...

  10. Keras 中 TimeDistributed 和 TimeDistributedDense 理解

    From the offical code: class TimeDistributed(Wrapper): """This wrapper applies a laye ...