1、直接声明:var slice []int

2、new: slice := *new([]int)

3、字面量:slice := []int{1,2,3,4,5}

4、make: slice :=  make([]int, 5, 10)

5、从切片或数组“截取”:slice := array[1:5] 或 slice := sourceSlice[1:5]

Golang Slice,以及append函数的陷阱:

slice并不是单纯的一个指向数组的指针,它是一个结构体(包含:指针,长度,容量)

先看一个小例子:

func main() {
a := make([]int, 2, 2)
a[0], a[1] = 1, 2 b := append(a[0:1], 3)
c := append(a[1:2], 4) fmt.Println(b,c)
}

在这个小例子中,原本是希望将a[0:1]作为b的前缀,然后追加上3;将a[1:2]作为c的前缀,然后追加上4。

但实际上输出结果并不是原本期望的[1 3] [2 4],而变成了[1 3] [3 4]。这是为什么呢?

我们知道数据结构中数组是非常高效的,可以直接寻址,但是有个缺陷,难以扩容。所以slice被设计为指向数组的指针,

在需要扩容时,(会将底层数组上的值复制到一个更大的数组)上然后指向这个新数组。

slice有个特性是允许多个slice指向同一个底层数组,这是一个有用的特性,在很多场景下都能通过这个特性实现 no copy 而提高效率。

但共享同时意味着不安全。b在追加3时实际上覆盖了a[1],导致c变成了[3 4]

怎么解决呢?防止共享数据的出现问题需要注意两条,只读和复制,或者统一归纳为不可变。

写法1,make出一个新slice,然后先copy前缀到新数组上再追加:

func main() {
a := make([]int, 2, 2)
a[0], a[1] = 1, 2 b := make([]int, 1)
copy(b, a[0:1])
b = append(b, 3) c := make([]int, 1)
copy(c, a[1:2])
c = append(c, 4) fmt.Println(b, c)
}

写法2,利用go中slice的一个小众语法,a[0:1:1] (源[起始index,终止index,cap终止index]),强迫追加时复制到新数组。

func main() {
a := make([]int, 2, 2)
a[0], a[1] = 1, 2 b := append(a[0:1:1], 3)
c := append(a[1:2:2], 4) fmt.Println(b, c)
}

go 创建slice的方式的更多相关文章

  1. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  2. Wireshark工具创建过滤器的方式

    Wireshark工具创建过滤器的方式  [实例1-3]现在要抓取目的或来源地址为192.168.5.9的封包.在图1.5中添加如下所示的条件: tcp dst port 3128 添加后单击Star ...

  3. Java多线程学习总结--线程概述及创建线程的方式(1)

    在Java开发中,多线程是很常用的,用得好的话,可以提高程序的性能. 首先先来看一下线程和进程的区别: 1,一个应用程序就是一个进程,一个进程中有一个或多个线程.一个进程至少要有一个主线程.线程可以看 ...

  4. JS面向对象编程创建类的方式

    js创建类的方式有几种,大致如下: 1,构造函数方式: function Car(parameters) { this.name = "objectboy"; } var cat1 ...

  5. java中创建多线程的方式

    在java中比较常用的有三种创建多线程的方式. 方式一:继承Thread类,要重写run方法. 在MyThread类 public class MyThread extends Thread { @O ...

  6. Java进阶(四十二)Java中多线程使用匿名内部类的方式进行创建3种方式

    Java中多线程使用匿名内部类的方式进行创建3种方式 package cn.edu.ujn.demo; // 匿名内部类的格式: public class ThreadDemo { public st ...

  7. 7. Callable 创建线程的方式三

    package com.gf.demo06; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionEx ...

  8. Vue 创建组件的方式

    Vue 创建组件的方式 2018年08月07日 11:10:56 虔诚带着决然 阅读数:1015   版权声明:本文为博主原创文章,未经博主允许不得用做其他商业活动. https://blog.csd ...

  9. @Scope注解设置创建bean的方式和生命周期

    1.1.1            Scope注解创建bean的方式和生命周期 作用 Scope设置对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式. 取 ...

随机推荐

  1. 限制IP每分钟访问10次

    转载:https://www.jianshu.com/p/d1326ab657ff IP请求限制,之前用过redis的set设置时间戳一分钟过期:也用过nginx的IP限流配置.前者,没法解决“用户在 ...

  2. deeplearning.ai 构建机器学习项目 Week 1 机器学习策略 I

    这门课是讲一些分析机器学习问题的方法,如何更快速高效的优化机器学习系统,以及NG自己的工程经验和教训. 1. 正交化(Othogonalization) 设计机器学习系统时需要面对一个问题是:可以尝试 ...

  3. 一致性 hash 算法( consistent hashing )及java实现

    consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在cache 系统中应用越来越广泛: 1 基 ...

  4. mapreduce.shuffle set in yarn.nodemanager.aux-services is invalid

    15/07/01 20:14:41 FATAL containermanager.AuxServices: Failed to initialize mapreduce.shuffle java.la ...

  5. MongoDB的初级安装和使用

    对于非关系型数据库,很多人不是很清楚,我也是作为新手慢慢摸索, 外网地址下载贼慢:我烦放在自己的百度网盘里 软件链接:https://pan.baidu.com/s/1A7h4VOfvm8N2gnlJ ...

  6. caffe之那些依赖的库

    1. Boost库 Boost是一个可移植的,提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一.Boost强调对跨平台的支持,编译与平台无关.Caffe采用C++为主要开发语言 ...

  7. 吴裕雄--天生自然 R语言开发学习:分类(续二)

    #-----------------------------------------------------------------------------# # R in Action (2nd e ...

  8. S07

    push 和 append 的表现不同, push 一次只添加单个参数到列表末端, append 一次可以添加多个参数. use v6; my @d = ( [ 1 .. 3 ] ); @d.push ...

  9. mongodb 4.0配置认证模块

    use admin db.createUser({user:"root",pwd:"xxx",roles:[{role:"root",db: ...

  10. WiFi产生电磁辐射或让人想去自杀

    随着互联网在生活中的地位越来越重要,WiFi作为一种无线连接方式给了用户极大的便捷,然而有一部分科学家提出WiFi产生的电磁反应会对人的健康受到影响.面对这种说法,我们一直以为是专家在危言耸听,但是如 ...