分享
  1. 首页
  2. 文章

通过 深入对比 Arrays 和 Slices 学习GO

_西门吹牛 · · 849 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

通过 深入对比 Arrays 和 Slices 学习GO

数组定义

package main
import (
 "fmt"
)
func main() {
 var arr [3]int //int 数组,长度为3 ,并且初始值都为0 
 fmt.Println(arr) // output:[0 0 0]
}复制代码

因为很简单的基础知识,就不一一解释了。

数组使用

package main
import (
 "fmt"
)
func main() {
 arr := [3]int{12, 78, 50} //int 数组,长度为3 ,并且初始化
 fmt.Println(arr) // output:[12 78 50]
}复制代码

上面通过简写的方式声明了数组,并且赋值,但并不是需要为所有元素分配值。如下程序:

package main
import (
 "fmt"
)
func main() {
 arr := [3]int{12} //int 数组,长度为3 ,并且初始化一个值
 fmt.Println(arr) // output:[12 0 0]
}复制代码

上面程序中哪个 arr 是一个长度为3的数组,只给第0为初始化为12,其他值依旧被默认初始化为0。善于"偷懒"的程序员往往是高手,比如你可以忽略数组的长度,让编译器帮我们去设置,如下:

package main
import (
 "fmt"
)
func main() {
 arr := [...]int{12, 78, 99} //int 数组,长度为3 ,并且初始化一个值
 fmt.Println(arr) // output:[12 0 0]
}复制代码

通过 ... 编译器可以自动找到数组长度,不同长度的数组类型是属于不同类型,比如:

package main
func main() {
 a := [3]int{5, 78, 8}
 var b [5]int
 b = a //cannot use a (type [3]int) as type [5]int in assignment
}复制代码

编译器直接抛出错误: cannot use a (type [3]int) as type [5]int in assignment

Arrays 属于值类型,也就意味着,如果你将数组赋值给一个新的变量,对新的变量进行修改,将不会影响原有的变量。

package main
import "fmt"
func main() {
 a := [3]int{5, 78, 8}
 var b = a
 b[0] = 100
 fmt.Println(a)
 fmt.Println(b)
}复制代码

output:

[5 78 8]
[100 78 8]复制代码

修改了b,a没有被修改,可见数组的赋值是一个值拷贝。

Slice 定义

package main
import (
 "fmt"
)
func main() {
 a := [5]int{76, 77, 78, 79, 80}
 var b []int = a[1:4] // 基于数组 a 创建一个 slice b
 fmt.Println(b) // [77 78 79]
}复制代码

上面我们创建了一个 slice 基于数组A,开始于数组的第一位结束于数组的第四位(不包含),然后我们看看改变数组a 会发生什么:

package main
import (
 "fmt"
)
func main() {
 a := [5]int{76, 77, 78, 79, 80}
 var b []int = a[1:4] // 基于数组 a 创建一个 slice b
 fmt.Println(b) // [77 78 79]
 a[1] = 100
 fmt.Println(b) // [100 78 79]
}复制代码

修改了a[1],结果b[1]的值也修改了,可以看到 slice 是对 数组 a 的应用, slice b 的底层存储实际是数组 b。 为什么是这样呢?可以查看文章[深入理解 Slice](https://github.com/lvgithub/go_blog/blob/master/Books/slice.md)

如果我不想基于某个数组去创建 Slice 可以吗,也是可以的:

package main
import (
 "fmt"
)
func main() {
 i := make([]int, 5, 5)
 fmt.Println(i)
 j := []int{}
 j = append(j, 1)
 fmt.Println(j)
}复制代码

上面通过两种方式创建了 Slice ,尤其注意,make 的方式可以设置 slice 的长度和容量。

package main
import (
 "fmt"
)
func main() {
 i := make([]int, 5, 5)
 fmt.Println(i)
 var j []int
 if j == nil {
 fmt.Printf("before append: j is nil\n")
 }
 j = append(j, 1)
 if j == nil {
 fmt.Printf("after append: j is nil\n")
 }
 fmt.Printf("i len:%d cap:%d \n", len(i), cap(i))
}
复制代码

output:

[0 0 0 0 0]
before append: j is nil
i len:5 cap:5 复制代码

如上程序,Go 为 slice 提供了两个内置的函数 len() cap()用来获取 slice 的长度和容量,append 来给 slice 扩充数据。不像数组一样直接通过 length 属性来获取长度。 还要一个细节 slice 不是值类型,因此可以通过 j == nil 来判断,数组是值类型如果这样会报错:

package main
func main() {
 i := [2]int{3, 1}
 if i == nil { //cannot convert nil to type [2]int
 }
}复制代码

编译报错:cannot convert nil to type [2]int

内存优化

slice 在一定的情况下,非常有利于我们优化内存,不需要开辟新的内存空间,这时候只要切片在内存中,就无法对被引用的数组进行垃圾回收,所以当我们遇到一个非常大的数组时,而我们只对其中小部分感兴趣,此时我们应该使用 copy 函数生成该 slice 的副本,使得原数组可以被回收,代码如下:

package main
import (
 "fmt"
)
func main() {
 i := []int{1, 3, 4, 56, 3}
 fmt.Println(i)
 j := make([]int, 5, 5)
 copy(j, i)
 fmt.Println(j)
}复制代码

参考

Arrays and Slices更多内容,欢迎关注我的Github


有疑问加站长微信联系(非本文作者)

本文来自:掘金

感谢作者:_西门吹牛

查看原文:通过 深入对比 Arrays 和 Slices 学习GO

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
849 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏