一、一般操作

  1,声明变量,go自动初始化为nil,长度:0,地址:0,nil

func main(){
var ss []string;
fmt.Printf("length:%v \taddr:%p \tisnil:%v",len(ss),ss, ss==nil)
} ---
Running... length: addr:0x0 isnil:true
Success: process exited with code .

  2,切片的追加,删除,插入操作

func main(){
    var ss []string;
    fmt.Printf("[ local print ]\t:\t length:%v\taddr:%p\tisnil:%v\n",len(ss),ss, ss==nil)    
    print("func print",ss)
    //切片尾部追加元素append elemnt
    for i:=0;i<10;i++{
        ss=append(ss,fmt.Sprintf("s%d",i));
    }
    fmt.Printf("[ local print ]\t:\tlength:%v\taddr:%p\tisnil:%v\n",len(ss),ss, ss==nil)    
    print("after append",ss)
    //删除切片元素remove element at index
    index:=5;
    ss=append(ss[:index],ss[index+1:]...)
    print("after delete",ss)
    //在切片中间插入元素insert element at index;
//注意:保存后部剩余元素,必须新建一个临时切片
    rear:=append([]string{},ss[index:]...)
    ss=append(ss[0:index],"inserted")
    ss=append(ss,rear...)
    print("after insert",ss)
}
func print(msg string,ss []string){
    fmt.Printf("[ %20s ]\t:\tlength:%v\taddr:%p\tisnil:%v\tcontent:%v",msg,len(ss),ss, ss==nil,ss)    
    fmt.Println()
}
------
Running... [ local print ]    :     length:0    addr:0x0    isnil:true
[           func print ]    :    length:0    addr:0x0    isnil:true    content:[]
[ local print ]    :    length:10    addr:0xc208056000    isnil:false
[         after append ]    :    length:10    addr:0xc208056000    isnil:false    content:[s0 s1 s2 s3 s4 s5 s6 s7 s8 s9]
[         after delete ]    :    length:9    addr:0xc208056000    isnil:false    content:[s0 s1 s2 s3 s4 s6 s7 s8 s9]
[         after insert ]    :    length:10    addr:0xc208056000    isnil:false    content:[s0 s1 s2 s3 s4 inserted s6 s7 s8 s9] Success: process exited with code 0.

  3,copy的使用。

在使用copy复制切片之前,要保证目标切片有足够的大小,注意是大小,而不是容量,还是看例子:

func main() {
var sa = make ([]string,);
for i:=;i<;i++{
sa=append(sa,fmt.Sprintf("%v",i)) }
var da =make([]string,,);
var cc=;
cc= copy(da,sa);
fmt.Printf("copy to da(len=%d)\t%v\n",len(da),da)
da = make([]string,)
cc=copy(da,sa);
fmt.Printf("copy to da(len=%d)\tcopied=%d\t%v\n",len(da),cc,da)
da = make([]string,)
cc =copy(da,sa);
fmt.Printf("copy to da(len=%d)\tcopied=%d\t%v\n",len(da),cc,da) } ---
Running... copy to da(len=) []
copy to da(len=) copied= [ ]
copy to da(len=) copied= [ ]

  从上面运行结果,明显看出,目标切片大小0,容量10,copy不能复制。目标切片大小小于源切片大小,copy就按照目标切片大小复制,不会报错。

二、初始大小和容量

  当我们使用make初始化切片的时候,必须给出size。go语言的书上一般都会告诉我们,当切片有足够大小的时候,append操作是非常快的。但是当给出初始大小后,我们得到的实际上是一个含有这个size数量切片类型的空元素,看例子:

func main(){
var ss=make([]string,);
ss=append(ss,"last");
print("after append",ss) }
---
Running... [         after append ]    :    length:11    addr:0xc20804c000    isnil:false    content:[          last]

  实际上,此时我们应该先用下标为切片元素负值。但是如果我们既想有好的效率,有想继续使用append函数而不想区分是否有空的元素,此时就要请出make的第三个参数,容量,也就是我们通过传递给make,0的大小和足够大的容量数值就行了。

func main(){
var ss=make([]string,,);
ss=append(ss,"last");
print("after append",ss) } ---
Running... [ after append ] : length: addr:0xc20804a000 isnil:false content:[last]

三、切片的指针。

  1,当我们用append追加元素到切片时,如果容量不够,go就会创建一个新的切片变量,看下面程序的执行结果:

func main() {
var sa []string
fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);
for i:=;i<;i++{
sa=append(sa,fmt.Sprintf("%v",i))
fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);
}
fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa); } ---
Running ...
addr:0x0 len: content:[]
addr:0x1030e0c8 len: content:[]
addr:0x10328120 len: content:[ ]
addr:0x10322180 len: content:[ ]
addr:0x10322180 len: content:[ ]
addr:0x10342080 len: content:[ ]
addr:0x10342080 len: content:[ ]
addr:0x10342080 len: content:[ ]
addr:0x10342080 len: content:[ ]
addr:0x10324a00 len: content:[ ]
addr:0x10324a00 len: content:[ ]
addr:0x10324a00 len: content:[ ] //很明显,切片的地址经过了数次改变。

  2,如果,在make初始化切片的时候给出了足够的容量,append操作不会创建新的切片:

func main() {
var sa = make ([]string,,);
fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);
for i:=;i<;i++{
sa=append(sa,fmt.Sprintf("%v",i))
fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);
}
fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa); }
addr:0x10304140         len: content:[]
addr:0x10304140 len: content:[]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ]
addr:0x10304140 len: content:[ ] //可见,切片的地址一直保持不变

  3, 如果不能准确预估切片的大小,又不想改变变量(如:为了共享数据的改变),这时候就要请出指针来帮忙了,下面程序中,sa就是osa这个切片的指针,我们共享切片数据和操作切片的时候都使用这个切片地址就ok了,其本质上是:append操作亦然会在需要的时候构造新的切片,不过是将地址都保存到了sa中,因此我们通过该指针始终可以访问到真正的数据。

func main() {
    var osa = make ([]string,0);
    sa:=&osa;
    for i:=0;i<10;i++{
        *sa=append(*sa,fmt.Sprintf("%v",i))
        fmt.Printf("addr of osa:%p,\taddr:%p \t content:%v\n",osa,sa,sa);
    }
    fmt.Printf("addr of osa:%p,\taddr:%p \t content:%v\n",osa,sa,sa);
   
} ---
Running... addr of osa:0xc20800a220,    addr:0xc20801e020      content:&[0]
addr of osa:0xc20801e0a0,    addr:0xc20801e020      content:&[0 1]
addr of osa:0xc20803e0c0,    addr:0xc20801e020      content:&[0 1 2]
addr of osa:0xc20803e0c0,    addr:0xc20801e020      content:&[0 1 2 3]
addr of osa:0xc208050080,    addr:0xc20801e020      content:&[0 1 2 3 4]
addr of osa:0xc208050080,    addr:0xc20801e020      content:&[0 1 2 3 4 5]
addr of osa:0xc208050080,    addr:0xc20801e020      content:&[0 1 2 3 4 5 6]
addr of osa:0xc208050080,    addr:0xc20801e020      content:&[0 1 2 3 4 5 6 7]
addr of osa:0xc208052000,    addr:0xc20801e020      content:&[0 1 2 3 4 5 6 7 8]
addr of osa:0xc208052000,    addr:0xc20801e020      content:&[0 1 2 3 4 5 6 7 8 9]
addr of osa:0xc208052000,    addr:0xc20801e020      content:&[0 1 2 3 4 5 6 7 8 9]

【玩转Golang】slice切片的操作——切片的追加、删除、插入等的更多相关文章

  1. golang slice 切片原理

    golang 中的 slice 非常强大,让数组操作非常方便高效.在开发中不定长度表示的数组全部都是 slice .但是很多同学对 slice 的模糊认识,造成认为golang中的数组是引用类型,结果 ...

  2. golang slice切片的原理以及内置函数cap, len

    golang中slice(切片)是常用的类型, slice是对数组进行封装 package main import ( "fmt" "strconv") fun ...

  3. golang 学习笔记 ---数组/字符串/切片

    数组 数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成.数组的长度是数组类型的组成部分.因为数组的长度是数组类型的一个部分,不同长度或不同类型的数据组成的数组都是不同的类 ...

  4. golang学习笔记 ---数组与切片

    数组: golang数组包含的每个数据称为数组元素(element),数组包含的元素个数被称为数组长度(length). golang数组的长度在定义后不可更改,并且在声明时可以是一个常量或常量表达式 ...

  5. python-类对象以列表切片模式操作

    #类对象以列表切片模式操作 class Person: def __init__(self): self.cache=[] def __setitem__(self, key, value): #修改 ...

  6. Go切片的操作

    package main import "fmt" //切片的操作 func main() { //创建slice var s []int //zero value for sli ...

  7. golang中的文件操作

    一.文件的基本介绍 文件是数据源(保存数据的地方)的一种,比如经常使用的word文档,txt文件,excel文件都是文件.文件最主要的作用就是保存数据,它既可以保存一张图片,也可以保持视频,声音等等. ...

  8. Golang Slice 总结

    数组 Go的切片是在数组之上的抽象数据类型,因此在了解切片之前必须要要理解数组.数组类型由指定和长度和元素类型定义.数组不需要显式的初始化:数组元素会自动初始化为零值:Go的数组是值语义.一个数组变量 ...

  9. golang slice 源码解读

    本文从源码角度学习 golang slice 的创建.扩容,深拷贝的实现. 内部数据结构 slice 仅有三个字段,其中array 是保存数据的部分,len 字段为长度,cap 为容量. type s ...

随机推荐

  1. [转]mysql update case when和where之间的注意事项

    原文地址:http://www.cnblogs.com/rwxwsblog/p/4512061.html 在日常开发中由于业务逻辑较为复杂,常常需要用到UPDATE和CASE...WHEN...THE ...

  2. MVC源码学习之AuthorizeAttribute

    常见的Controller定义方式: public class HomeController : Controller { public ActionResult Index() { return V ...

  3. 代码动态设置edittext输入类型为密码类型

    开发中常常会用到EditText输入框,要将他的输入类型设置为密码输入,但是直接在布局文件中设置时,hint字体风格就会不一样 例如,在布局文件中直接设置是这样的(如下图),字体风格明显跟上一行的不一 ...

  4. 关于div一侧固定,另一侧自适应

    关于div一侧固定,另一侧自适应,从文字看出 一侧固定:说明有固定长度, 一侧自适应:说明是按比例缩放 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML ...

  5. Change Data template dynamically

    1. Attached Property bound to task state. Any change will dynamically set data template.2. Visual St ...

  6. Oracle Grid Infrastructure Installation Guide for Linux 以debug模式安装并记录日志

    最新文章:Virson's Blog 使用如下命令能够以debug模式安装Oracle Grid并将日志记录到文件 [grid@vdb1 11ggrid]$ ./runInstaller -debug ...

  7. Numpy的array数组和标量之间的运算

    矢量化 数组很重要,因为它使你不用编写循环即可对数据执行批量运算.这通常就叫做矢量化(vectorzation) 数组与数组的运算 数组与标量的算术运算

  8. 【转】【WCF】WCF中客户端生成代理的两种方式

    WCF程序中客户端要生成代理才能调用服务,在客户端生成代理有多种方式,如用ChannelFactory和添加服务引用等.下面就分别来介绍下这两种生成代理的方式. 使用ChannelFactory 使用 ...

  9. 【转载】Exchange 2010配置与安装实用手册

    Exchange 2010配置与安装实用手册 在Exchange 2010配置的时候主要分三大部分,这分别是网络配置.准备存储以及相关的安装策略和过程.同时还需要注意和其他的Windows软件相协调. ...

  10. Android 耳机插入过程分析

    Android 耳机插入过程分析 参考链接: https://www.jianshu.com/p/d82a8dabb3e7 初始化: 10-26 07:40:43.932 1414 1414 I Sy ...