当前位置: 首页 > news >正文

go中的slice

组成

指针、长度和容量

大小

slice占用24个字节
array:执向底层数组的指针,占用8个字节
len:切片的长度,占用8个字节
cap:切片的容量,占用8个字节

四种初始化方式

var slice1 []int
slice2 := []int{1, 2, 3, 4}
slice3 := make([]int,3,5)
// 从其他array中街区
slice4 := arr[1:3]

slice和array的区别

数组的长度固定,数组是值类型(值类型有基本数据类型,结构体类型),slice的值长度可变,属于引用类型(引用类型:字典类型,通道类型,函数类型)切片是引用传递,所以它们不需要使用额外的内存并且比使用数组更有效率

扩容策略

  1. 首先判断,如果新申请的容量(cap)大于2倍的旧容量(old.cap),最终容量就是新申请的容量
  2. 否则判断,如果旧切片的长度(len)大于1024,则最终容量就是旧容量的两倍
  3. 否则判断,如果旧切片长度(len)大于等于1024,则最终容量从旧容量开始循环增加原来的1/4,直到最终容量大于等于新申请的容量
  4. 如果最终容量计算值溢出,则最终容量就是新申请容量

slice深拷贝和浅拷贝

浅拷贝

a := []int{1, 2, 3}
b := a //地址的拷贝,浅拷贝
fmt.Println(a, b)

a[0] = 1000
fmt.Println(a, b)

b[2] = 4000
fmt.Println(a, b)

/*
执行结果
[1 2 3] [1 2 3]
[1000 2 3] [1000 2 3]
[1000 2 4000] [1000 2 4000]
*/

深拷贝

a := []int{1, 2, 3}
b := make([]int, 0)     //创建新切片
b = append(b, a[:]...)
fmt.Println(a, b)
a[1] = 1000
fmt.Println(a, b)
fmt.Printf("%p,%p", a, b)

/*
执行结果
[1 2 3] [1 2 3]
[1 1000 3] [1 2 3]
0xc0000b4018,0xc0000b4030% 
*/

线程安全性

slice是非线程安全的,因为底层数组是通过指针来引用的,该指针是非线程安全的(索引位覆写)

func main() {
 var s []string
 for i := 0; i < 9999; i++ {
  go func() {
   s = append(s, "脑子进煎鱼了")
  }()
 }

 fmt.Printf("进了 %d 只煎鱼", len(s))
}

执行结果肯定对不上9999,这就是索引位覆写
解决办法:

  1. 加互斥锁
package main

import (
	"fmt"
	"sync"
	"time"
)

var s []int
var lock sync.Mutex 

func appendSlice(i int) {
	lock.Lock()
	s = append(s, i)
	lock.Unlock()
}

func main() {
	
	for i := 0; i < 10000; i++ {
		go appendSlice(i)
	}
	time.Sleep(time.Second)
	for i, v := range s {
		fmt.Println(i, ":", v)
	}
}
  1. 使用协程来维护slice
for {
    data := <- chanList
    list = append(list, data)
}

相关文章:

  • 什么是完全的静态分析?
  • 如何在ios手机上使用动态代理?
  • 搭建zookeeper集群
  • React生命周期详解
  • 大数据项目中数据倾斜
  • Kafka Consumer源码讲解
  • svg中 path标签的d属性
  • 什么样的数字IC后端工程师能拿到高薪Offer?
  • 计算机组成原理_DRAM和SRAM
  • 两个有序序列的中位数
  • 浅析Android UI——View 的绘制
  • 一文看懂25个神经网络模型,神经网络神经元模型
  • 神经网络模型训练过程,神经网络模型应用实例
  • NR PDCCH(二) SearchSpace
  • Vue2(十二):Vuex环境搭建、Vuex工作原理、几个配置项、多组件共享数据、Vuex模块化
  • 【译】JS基础算法脚本:字符串结尾
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • Java知识点总结(JavaIO-打印流)
  • js作用域和this的理解
  • Laravel5.4 Queues队列学习
  • opencv python Meanshift 和 Camshift
  • PaddlePaddle-GitHub的正确打开姿势
  • Twitter赢在开放,三年创造奇迹
  • vue总结
  • 初识 beanstalkd
  • 浅谈Golang中select的用法
  • 区块链分支循环
  • 算法-图和图算法
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • #pragma once与条件编译
  • #WEB前端(HTML属性)
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (1)Android开发优化---------UI优化
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (pojstep1.3.1)1017(构造法模拟)
  • (阿里云万网)-域名注册购买实名流程
  • (层次遍历)104. 二叉树的最大深度
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (转) RFS+AutoItLibrary测试web对话框
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET/C# 避免调试器不小心提前计算本应延迟计算的值
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .sys文件乱码_python vscode输出乱码
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——
  • [APIO2012] 派遣 dispatching