详解go语言的array和slice 【二】

简介:

 上一篇  详解go语言的array和slice 【一】已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多。上一篇的最后讲解到创建新的slice时使用第三个索引来限制slice的容量,在操作新slice时,如果新slice的容量大于长度时,添加新元素依然后使源的相应元素改变。这一篇里我会讲解到如何避免这些问题,以及迭代、和做为方法参数方面的知识点。

slice的长度和容量设置为同一个值

  如果在创建新的slice时我们把他的长度和容量的值设置为样的值,那么在append新元素时,底层会创建一个新的array并把之前的值复制过去。这样就不会影响之前共同的底层array了。

复制代码
    // 创建一个容量和长度均为6的slice
    slice1 := []int{5, 23, 10, 2, 61, 33}
    // 对slices1进行切片,长度为2容量为3
    slice2 := slice1[1:3:3]
    fmt.Println("cap", cap(slice2))
    fmt.Println("slice2", slice2)

    //修改一个共同指向的元素
    //两个slice的值都会修改
    slice2[0] = 11111
    fmt.Println("slice1", slice1)
    fmt.Println("slice2", slice2)

    // 增加一个元素
    slice2 = append(slice2, 55555)

    fmt.Println("slice1: ", slice1)
    fmt.Println("slice2: ", slice2)
复制代码

  输出结果

cap 2
slice2 [23 10]
slice1 [5 11111 10 2 61 33]
slice2 [11111 10]
slice1:  [5 11111 10 2 61 33]
slice2:  [11111 10 55555]

  代码中的长度和容量是一样的,长度和容量的计算公式看我的上一篇博客。增加一个元素后,原来共同指向的底层数据是没有变的。因为slice2的底层array被重新赋值了。

迭代slice

  go语言内置一个关键字range用于迭代集合,当然他也可以迭代slice,也可以使用  _  来忽略我们不关心的元素,但是如果只关心index则不需这么写 for index,_ := range slice1。下在给出完整代码

复制代码
    // 创建一个容量和长度均为6的slice
    slice1 := []int{5, 23, 10, 2, 61, 33}

    for index, value := range slice1 {
        fmt.Println("index: ", index, " value: ", value)
    }

    // 可以忽略我们不关心的元素
    // 只关心value
    for _, value := range slice1 {
        fmt.Println("value ", value)
    }

    // 只关心index, 可以不用 _
    for index := range slice1 {
        fmt.Println("index: ", index)
    }
复制代码

 

   需要注意的是rang 迭代的value值并是一个复本,我们可以对比一下迭代的value和原slice内相应index下value的地址:

复制代码
    // 创建一个容量和长度均为6的slice
    slice1 := []int{5, 23, 10, 2, 61, 33}

    for index, value := range slice1 {
        fmt.Println("index: ", index, " value address : ", &value, " slice1 value address", &slice1[index])

    }
复制代码

  输出结果

index:  0  value address :  0xc04204e088  slice1 value address 0xc04206a030
index:  1  value address :  0xc04204e088  slice1 value address 0xc04206a038
index:  2  value address :  0xc04204e088  slice1 value address 0xc04206a040
index:  3  value address :  0xc04204e088  slice1 value address 0xc04206a048
index:  4  value address :  0xc04204e088  slice1 value address 0xc04206a050
index:  5  value address :  0xc04204e088  slice1 value address 0xc04206a058

  slice1中value的地址是不断变化的。而迭代的value值的地址没有变化,这是因为value是一个变量,为次迭代的时候赋不同的值。我们把代码写成下面这样,你就清楚了

    var index, value int
    for index, value = range slice1 {
        fmt.Println("index: ", index, &index, " value address : ", &value, " slice1 value address", &slice1[index])

    }

   除了使用rang 也可以使用传统的for循环来做迭代

    slice1 := []int{5, 23, 10, 2, 61, 33}
    
    for i, len := 1, len(slice1); i < len; i++ {
        fmt.Println("index: ", i, " value:", slice1[i])
    }

 

 slice作为方法参数

   由于slice的特殊结构,有一个指针指向一个数组

    s := make([]int, 2, 5)
    fmt.Println("len: ", len(s))
    fmt.Println("cap: ", cap(s))
    s = append(s, 2)

    s[0] = 12

 

  所以,slice做为方法的参数传递时,只会复制slice本身而不会复制slice底层的array.如果我们创建一个int类型有100万长度的slice ,把他传递给一个方法时,只需要复制24个字节就够了。指针需要8个,长度和容量都是8个。

复制代码
const size int = 1000 * 1000

func main() {
    slice0 := make([]int, size)
    fmt.Println("slice0 len: ", len(slice0), " cap :", cap(slice0))
    doSomeThing(slice0)
}

func doSomeThing(s []int) {
    fmt.Println(len(s))
}
复制代码

 

 

本文转自lpxxn博客园博客,原文链接:http://www.cnblogs.com/li-peng/p/7541554.html,如需转载请自行联系原作者

相关文章
|
2月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
206 1
|
10月前
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
|
10月前
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
4月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
299 1
|
4月前
|
Cloud Native Go API
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
401 0
|
4月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
261 0
|
4月前
|
Cloud Native Java 中间件
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
230 0
|
4月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
334 0
|
4月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。
|
4月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。