码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • golang——slice避坑


    • slice的结构
    • append的性能损耗
    • 母子切片共享
    • 切片导致内存泄漏
    • 函数参数需要传切片的指针吗
    • 遍历slice时修改slice

    slice的结构

    type slice struct {
      array unsafe.Pointer
      len int
      cap int
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    slice结构如上代码,由三个field组成,分别是指向底层数组的指针,标识有效元素长度的len和标识空间大小的cap。

    append的性能损耗

    golang的slice类似于c++的vector,都是有len和cap的,当len

    所以,如果len

    append扩容:

    • 切片相对于数组最大的特点就是可以追加元素,可以自动扩容
    • 追加的元素放到预留的内存空间里,同时len+1
    • 如果预留空间已用完,则会重新申请一块更大的内存空间,capacity大约变成之前的2倍(cap<1024)或1.25倍(cap>1024)。把原内存空间的数据拷贝过来,在新内存空间上执行append操作

    母子切片共享

    假设有两个切片如下:

    parent := make([]int, 3, 5) //len=3, cap=5
    child := parent[1:3] //len=2, cap=4	
    
    • 1
    • 2
    • 刚开始,子切片和母切片共享底层的内存空间,修改子切片会反映到母切片上,在子切片上执行append会把新元素放到母切片预留的内存空间上
    • 当子切片不断执行append,耗完了母切片预留的内存空间,子切片跟母切片就会发生内存分离,此后两个切片没有任何关系

    切片导致内存泄漏

    func returnSubSlice() []int {
      parent := make([]int, TOTAL)
      child := parent[begin:end]
      return child
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    如上代码,假设母切片占用内存8M,child切片是在parent基础上构造的占用内存1M,子切片和母切片共享同一块内存,当函数返回后,母切片已经不在使用,本该进行释放,但是由于和子切片公用一块内存未释放母切片,造成了7M的内存泄漏,正确做法应该是给子切片开辟空间,然后for循环将需要的数据从母切片拷贝到子切片上,然后返回子切片。

    函数参数需要传切片的指针吗

    前边说切片的结构中又3个field:指向底层数组的指针、表示有效元素的长度len、表示空间的cap

    • 当len和cap要变时,需要传切片指针
      *arr = append(*arr, 9)
      
      • 1
    • len、point和cap要变,需要传切片指针
      *arr = (*arr)[1:2]
      
      • 1
    • slice中的3个field都不变,只修改底层数组,不需要传切片指针

    遍历slice时修改slice

    sli := []int{1, 2, 3}
    //方法一
    for _, v := range sli {
    	v = v + 1
    }
    //方法二
    for i, v := range sli {
    	sli[i] = v + 1
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如上两种方法种,只有方法二能成功在遍历是修改slice中的值。因为在用 for range遍历slice时,v取到的是slice中元素的拷贝,修改这个值,并不会影响元素本身。

  • 相关阅读:
    Linux - 进程
    「互动有礼,感谢有你」参与互动就有机会获赠 Navicat Premium 16
    【Day_15 0510】查找输入整数二进制中1的个数
    Appleid苹果账号自动解锁改密(自动解锁二验改密码)
    权限系统--前后端完全分离
    Day2多种抓包工具介绍以及使用封包监听工具找到挑战数据包实现发送数据包进行挑战
    golang学习笔记——指针
    人工智能学习:CIFAR-10数据分类识别-VGG网络(5)
    RFID与人工智能的融合:物联网时代的智能化变革
    三、Thread 类和Runnable 接口详解
  • 原文地址:https://blog.csdn.net/qq_43747991/article/details/126843622
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号