slice使用时需要注意的点 @ 胡巴 | 星期三,二月 9 日,2022 年 | 3 分钟阅读 | 更新于 星期三,二月 9 日,2022 年

关于golang中slice使用时需要注意的问题,未扩容前底层数组未变,修改任意一个slice都有可能导致另一个指向同一个底层数组的slice的值的修改,所以使用过程中需要特别注意。

package main

import "fmt"

func main() {
	arr1 := [...]int{1,2,3,4}
	fmt.Printf("arr1自身地址: %p value: %v\n", &arr1, arr1)

	sli1 := arr1[0:2]
	fmt.Printf("sli1自身地址: %p sli1底层数组指针地址: %p value: %v\n", &sli1, sli1, sli1)

	newSli1 := append(sli1, 5)
	fmt.Printf("newSli1自身地址: %p, newSli1底层数组地址: %p value: %v\n", &newSli1, newSli1, newSli1)
	fmt.Printf("当前arr1的value: %v\n", arr1)
	fmt.Printf("当前sli1的value: %v\n", sli1)

	sli1 = append(sli1, 7)
	fmt.Printf("sli1自身地址: %p sli1底层数组指针地址: %p value: %v\n", &sli1, sli1, sli1)
	fmt.Printf("当前arr1的value: %v\n", arr1)
	fmt.Printf("newSli1自身地址: %p, newSli1底层数组地址: %p value: %v\n", &newSli1, newSli1, newSli1)

	// arr1自身地址: 0xc00012e000 value: [1 2 3 4]
	// sli1自身地址: 0xc00011c018 sli1底层数组指针地址: 0xc00012e000 value: [1 2]
	// newSli1自身地址: 0xc00011c060, newSli1底层数组地址: 0xc00012e000 value: [1 2 5]
	// 当前arr1的value: [1 2 5 4]
	// 当前sli1的value: [1 2]
	// sli1自身地址: 0xc00011c018 sli1底层数组指针地址: 0xc00012e000 value: [1 2 7]
	// 当前arr1的value: [1 2 7 4]
	// newSli1自身地址: 0xc00011c060, newSli1底层数组地址: 0xc00012e000 value: [1 2 7]

	// ------------------上面是发生扩容之前--------------------

	// ------------------下面是发生扩容之后------------------------
	sli1 = append(sli1, 8, 9)
	fmt.Printf("sli1自身地址: %p sli1底层数组指针地址: %p value: %v\n", &sli1, sli1, sli1)
	fmt.Printf("当前arr1的value: %v\n", arr1)
	fmt.Printf("newSli1自身地址: %p, newSli1底层数组地址: %p value: %v\n", &newSli1, newSli1, newSli1)

	// 发生扩容后,底层数组从新非配内存,导致数组地址变化
	// sli1自身地址: 0xc00000c030 sli1底层数组指针地址: 0xc0000140c0 value: [1 2 7 8 9]
	// 当前arr1的value: [1 2 7 4]
	// newSli1自身地址: 0xc00000c078, newSli1底层数组地址: 0xc0000180c0 value: [1 2 7]

	temp := changeSli(sli1)
	fmt.Printf("sli1自身地址: %p sli1底层数组指针地址: %p value: %v\n", &sli1, sli1, sli1)
	fmt.Printf("temp自身地址: %p temp底层数组指针地址: %p value: %v\n", &temp, temp, temp)

	sli1[3] = 999
	fmt.Printf("temp自身地址: %p temp底层数组指针地址: %p value: %v\n", &temp, temp, temp)

	// sli2 := arr1[0:2:2]
	// fmt.Printf("sli2自身地址: %p sli2底层数组指针地址: %p value: %v\n", &sli2, sli2, sli2)
}

func changeSli(temp []int) []int {
	fmt.Printf("temp自身地址: %p temp底层数组指针地址: %p value: %v\n", &temp, temp, temp)
	// temp = append(temp, 10, 11, 12, 13, 14, 15)
	// 这里如果上面的append注释了,会改变外面的sli1底层的数组的值
	// 如果上面的append没有注释,则temp会发生扩容,下面就不会改变外面的sli1
	// temp[3] = 123

	temp = append(temp, 10)

	return temp
}

公众号: 无限递归

alt 搜索公众号:无限递归

Copyright © 2017 - 2018 boboidea.com All Rights Reserved 波波创意软件工作室 版权所有 【转载请注明出处】

avatar
基本信息
  • 姓名:bobo
  • 花名:胡巴
  • 性别:男
  • 血型:O型
  • 星座:白羊座

联系方式

  • 所在地:上海
  • QQ:279250819
  • 微信号:wanghuiwoshinideyou
  • 电子邮件:279250819@qq.com

博客地址

公众号

alt 无限递归

待学习的东西

  • docker
  • k8s
  • flink
  • flutter
  • golang源码
  • redis底层
  • 消息中间价原理
  • zabbix
  • opentracing
  • grafana
工作经历
  • 2019.6 - 至今

    • 公司:萌推(上海突进网络科技有限公司)
    • 职位:中级PHP工程师 & 初级golang工程师
    • 荣誉:
      • 绩效A连续得主
      • 月度之星
      • 优秀个人奖
    • 所作所为:
      • 利用ES优化OMS、MMS管理系统商品列表查询
      • 利用消息队列、Redis、乐观锁优化商品审核流程
      • 利用Redis对商家端接口进行有效限流
      • 优化商品相关表索引,提升SQL查询速度
      • 商品中台构建,统一商品相关操作
      • 大表优化(数据分离、分表、大字段拆分)
      • 掌握所有商品核心流程
  • 2018.5 - 2019.5

    • 公司:DaDa英语(上海卓赞教育信息科技有限公司)
    • 职位:中级PHP开发工程师
    • 荣誉:无
    • 所作所为:
      • 利用ES优化教师CMS系统统计数据接口至500ms内
      • 工单系统开发及持续优化
      • 教师CMS系统的功能开发及持续优化
  • 2018.3 - 2018.5

    • 公司:波奇(上海)信息科技有限公司
    • 职位:初级PHP开发工程师
    • 荣誉:同下
    • 所做作为:如下
  • 2016.7 - 2018.3

    • 公司:光橙(上海)信息科技有限公司
    • 职位:初级PHP开发工程师
    • 荣誉:
      • 年度最佳进步奖
    • 所作所为:
      • 利用Redis提升商详接口最佳响应速度至50ms内
      • 利用Redis提升双11活动页可承受QPS至500以上
      • 利用Redis对接口进行简单限流
      • 与小伙伴合作提升搜索质量(ES初识)
      • 其他C端接口的开发及优化
      • B端商城老页面的维护及优化
SKILLS

编程语言

  • PHP
  • Golang
  • Shell
  • JAVA
  • JS
  • HTML\CSS

数据库

  • MySQL
  • Redis
  • 具有简单分表经验

消息中间件

  • RabbitMq
  • Kafka

文档撰写

  • Swagger
  • Markdown

技术框架

  • Laravel
  • gin

搜索引擎

  • ElasticSearch

抓包工具

  • Charles