数组

同其他语言一样,数组是一些相同类型的元素的集合。数组声明

数组的类型为 n[T],其中 n 表示数组中元素的个数,T 表示数组中元素的类型。数组元素的个数 n 也是数组类型的一部分

 package main

 import "fmt"

 func main() {
var a []int //int array a and length is 5
fmt.Println(a)
}
var a [5]int 是我们常用的一种声明数组的方式。同时也会给数组种的所有元素赋值int的初始值0.运行代码我们得到:[0 0 0 0 0]

我们还可以用shorhand 速记声明的方式声明和赋值数组:
 package main

 import "fmt"

 func main() {
a := []int{, , , , } //int array a and length is 5
fmt.Println(a)
}

这个代码的运行结果是:[1 3 4 5 6]

如果没有给所有的元素赋值,那么后面的元素会被赋予默认值。

在声明数组的时候,可以使用...来代替数组长度,编译器会帮我们计算数组长度

 package main

 import "fmt"

 func main() {
a := [...]int{, , } //int array a and length is 3
fmt.Println(len(a))
}

这个代码的运行结果是3,表明编译器帮我们计算好了数组长度。

由于数组的长度属于数组类型的一部分,那么[3]int和[5]int 不是相同一类型,不可以相互赋值。

数组遍历

Go提供了for rang来让我们遍历数组,这样比用for 循环简洁一些。

 package main

 import "fmt"

 func main() {
a := [...]string{"a", "b"} for i, v := range a { //range returns both the index and value
fmt.Printf(" the element %d of a is %s \n", i, v)
}
}

上面的代码运行结果是:

the element 0 of a is a
the element 1 of a is b

切片

由于数组长度不可变,导致数组的应用场景大幅减少。还好Go给我们提供了切片。

把上面的代码稍微修改一下,我们来创建一个切片

 package main

 import "fmt"

 func main() {
a := [...]string{"a", "b", "c", "d", "e"} for i, v := range a { //range returns both the index and value
fmt.Printf(" the element %d of a is %s \n", i, v)
} b := a[:]
fmt.Println(b)
}

运行结果是

 the element  of a is a
the element of a is b
the element of a is c
the element of a is d
the element of a is e
[c]

我们通过 a[start:end] 这样的语法创建了一个从 a[start] 到 a[end -1] 的切片。在上面代码中,我们用这种方式创建了长度为1 的切片b。

我们还可以使用和创建数组相似的方式来创建切片

 package main

 import "fmt"

 func main() {
b := []string{"a", "b", "c", "d", "e"}
fmt.Println(b)
}

需要注意的是[]中间是没有长度或者...的。这段代码创建了一个切片b,然后代码的运行结果是:[a b c d e]

切片的长度和容量

切片的长度就是切片中元素的个数。切片的容量是 切片创建的数组的长度减去创建切片时的start值。

具体我们看代码

 package main

 import "fmt"

 func main() {
a := [...]string{"a", "b", "c", "d", "e"}
b := a[:]
fmt.Printf("length of slice %d capacity %d", len(b), cap(b)) //length is 1 and capacity is 4 }

运行结果是:length of slice 1 capacity 4

append 追加数据到切片上

 package main

 import "fmt"

 func main() {
a := [...]string{"a", "b", "c", "d", "e"}
b := a[:]
fmt.Printf("length of slice %d capacity %d\n", len(b), cap(b)) //length is 1 and capacity is 4
b = append(b, "x", "y", "z", "m", "n")
fmt.Printf("length of slice %d capacity %d\n", len(b), cap(b)) //length is 1 and capacity is 8 }

第8行代码给切片b追加了5个元素,那么长度就是6,长度超过了容量4,go是怎么做的?如果容量超了,go会创建一个新的数组,容量翻倍,然后返回新数组的完整切片。

代码的运行结果是

length of slice  capacity
length of slice capacity

我们还可以使用append把一个切片完整的追加到一个切片上:

 package main

 import "fmt"

 func main() {
a := []string{"a", "b"}
b := []string{"c", "d", "e"}
a = append(a, b...)
fmt.Println(a)
}

运行结果是:

[a b c d e]

这里有点类似ES6的写法

var arr = [1, 2, 3];

var arr1 = [...arr, 4, 5, 6]; 

切片是数组的一种外层表示,所以我们每次修改切片,最终都会将修改落到数组上。

但是这时候再修改切边,修改就不会再反应到原来的数组上。

make创建切片

我们还可以使用函数make来创建切片。func make([]T, len, cap) []T,其中cap参数是可选的。

 package main

 import "fmt"

 func main() {
a := make([]int, )
fmt.Println(a) }

切片和数组作为参数传递

先上两段代码,第一段:

package main

import "fmt"

func main() {
a := []string{"a", "b", "c", "d", "e"}
fmt.Println("before call function:", a)
changeZeroElementA(a)
fmt.Println("after call function:", a) b := []string{"a", "b", "c", "d", "e"}
fmt.Println("before call function:", b)
changeZeroElementB(b)
fmt.Println("after call function:", b)
} func changeZeroElementA(arr []string) {
//arr = []string{"X", "Y"}
arr[] = "changed"
}
func changeZeroElementB(arr []string) {
arr[] = "changed"
}

结果是:

before call function: [a b c d e]
after call function: [changed b c d e]
before call function: [a b c d e]
after call function: [a b c d e]

第二段:

package main

import "fmt"

func main() {
a := []string{"a", "b", "c", "d", "e"}
fmt.Println("before call function:", a)
changeZeroElementA(a)
fmt.Println("after call function:", a) b := []string{"a", "b", "c", "d", "e"}
fmt.Println("before call function:", b)
changeZeroElementB(b)
fmt.Println("after call function:", b)
} func changeZeroElementA(arr []string) {
arr = []string{"X", "Y"}
arr[] = "changed"
}
func changeZeroElementB(arr []string) {
arr[] = "changed"
}

运行结果:

 before call function: [a b c d e]
after call function: [a b c d e]
before call function: [a b c d e]
after call function: [a b c d e]

看到这里是不是有些奇怪,其实go里面一切都是值传递。这里有全方面的解释:https://stackoverflow.com/questions/39993688/are-golang-slices-pass-by-value

切片是数组的一种外层表示,所以我们每次修改切片,最终都会将修改落到数组上。

Golang: 数组和切片的更多相关文章

  1. Golang 数组、切片、映射

    定义数组 var arr1 [5]int //整型类型 fmt.Println(arr1) //[0 0 0 0 0] //赋值 arr1 = [5]int{1, 2, 3, 4, 5} fmt.Pr ...

  2. golang数组与切片

    golang中坑的慢慢踩! golang中的数组是值类型,函数调用是传入的是数组的拷贝,如果想改变数组的值,可考虑使用指针数组,即函数调用时传入数组的地址 golang中的切片是引用类型,但是在函数中 ...

  3. golang 数组、切片、map

    一.数组(类似python的list) 数组的长度一旦定义了就不能动态增长.并且存储的数据类型必须相同. 创建方法: var 数组名 [长度]数据类型 例如: package main import ...

  4. Golang数组和切片的区别

    大纲 数组是固定大小 切片不是动态数组,可以扩容 区别 定义方式不一样 初始化方法不一样 package main import "fmt" func main() { // -- ...

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

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

  6. golang 数组以及slice切片

    老虞学GoLang笔记-数组和切片   数组 Arrays 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值.在初始化后长度是固定的,无法修改其 ...

  7. 手把手golang教程【二】——数组与切片

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第五篇,这一篇我们将会了解golang中的数组和切片的使用. 数组与切片 golang当中数组和C++中的定义类似, ...

  8. golang笔记——数组与切片

    一.切片的定义 我们可以从数组(go语言中很少直接使用数组)或者切片来初始化一个新的切片,也可以直接通过 make 来初始化一个所有元素为默认零值的切片. //1.通过数组来初始化切片 arr := ...

  9. [Golang学习笔记] 07 数组和切片

    01-06回顾: Go语言开发环境配置, 常用源码文件写法, 程序实体(尤其是变量)及其相关各种概念和编程技巧: 类型推断,变量重声明,可重名变量,类型推断,类型转换,别名类型和潜在类型 数组: 数组 ...

随机推荐

  1. nginx upstream轮询配置

    nginx upstream nginx的upstream官方地址为:http://nginx.org/cn/docs/http/ngx_http_upstream_module.html 轮询分为多 ...

  2. 自己动手,丰衣足食!Python3网络爬虫实战案例

    本教程是崔大大的爬虫实战教程的笔记:网易云课堂 Python3+Pip环境配置 Windows下安装Python: http://www.cnblogs.com/0bug/p/8228378.html ...

  3. Redis和Memcache区别,优缺点对比

    1. Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等. 2.Redis不仅仅支持简单的k/v类型的数据,同时还提供li ...

  4. MySql开启远程账户登陆总结

    1.更改 "mysql" 数据库里的 "user" 表里的 "host" 项,从"127.0.0.1"改成"% ...

  5. [UE4]Wrap Box流布局

    一.Wrap Box的子控件可以根据Wrap Box的大小自动换行 1.Wrap Box.Inner Slot Padding:Wrap Box所有子控件留白,可以实现每个控件之间的间距都是相同,但是 ...

  6. 浅析负载均衡的6种算法,Ngnix的5种算法。

    浅析负载均衡的6种算法,Ngnix的5种算法.浮生偷闲百家号03-21 10:06关注内容导读其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果.源地址哈希的思想是根据获取客 ...

  7. 【Linux命令】Linux下的tar压缩解压缩命令详解(转)

    tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个 ...

  8. Linux下载命令之rpm和yum比较

    RPM和YUM比较 rpm 是linux的一种软件包名称,以.rmp结尾,安装的时候语法为:rpm -ivh,rpm包的安装有一个很大的缺点就是文件的关联性太大,有时候装一个软件要安装很多其他的软件包 ...

  9. [持续交付实践] pipeline使用:项目样例

    项目说明 本文将以一个微服务项目的具体pipeline样例进行脚本编写说明.一条完整的pipeline交付流水线通常会包括代码获取.单元测试.静态检查.打包部署.接口层测试.UI层测试.性能专项测试( ...

  10. Java限制可以重入次数的锁

    完全 模仿ReentrantLock, 通过继承 java.util.concurrent.locks.Lock , 内置 AbstractQueuedSynchronizer 实现类,限制可以重入次 ...