GO语言学习系列六——GO的数组 array与切片 slice

数组(array)

在GO语言中,数组是用于存储相同数据类型的集合,数组长度必须是一个常量表达式,且是一个非负数
GO语言中的数组是一种值类型,下文会介绍

数组定义的格式

var 数组名称 [数组长度]数组类型
例:
var arr [3]int

输出为:

[0 0 0]

在GO语言中,初始化数组时,给定了数组长度,但没给定数组下标的值,int类型默认值为0,string类型默认为空值,这是常用的两种类型

数组的赋值操作

// 第一种赋值操作
var arr = [3]int{1,2,3} //直接将值初始化,不同的类似初始化值不相同
// 第二种赋值操作
var arr [3]int  // 初始化数组变量
arr[1] = 1      // 给数组的下标赋值
// 第三种赋值操作
var arr  = [3]string{1:"one",2:"two"}
// 一般常用的就这三种,其它方式都是一些变相的操作,这里不做介绍

有必要说明一下:数组在初始中给定了数组的长度,用len(arr)-1可以得到数组的长度,如果赋值时操出数组的最大长度,在编译的时候将会报错

先来个练习加深下前面所说的影响,将一个int型数组的值全部乘以2

package main
import "fmt"
func main(){
    var arrs = [5]int{1, 2, 3, 4, 5}
    for i, v := range arrs {
        arrs[i] = v * 2
        fmt.Printf("index is %d,value is %d \n", i, arrs[i])
    }
}

输出为

index is 0,value is 2 
index is 1,value is 4 
index is 2,value is 6 
index is 3,value is 8 
index is 4,value is 10 

数组的值类型

在GO语言中,数组的存储是一种值的类型,不像C等其它语言是指向首元素的指针,所以在创建数组也可以通过new() 来创建一个指针数组
例:

var arr1 = new([5]int)
var arr2 [5]int

输出分别为

&[0 0 0 0 0]
[0 0 0 0 0]

&符号熟悉么,没错,他表明这是一个指针数组,在函数中传递时,不用将数组的值进行复制一遍

多维数组

在某种程度上面来说,多维数组其实就是将多个一维数组进行嵌套一种表达方式,例如:var arr1 [3][5]int
输出为[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
如果尝过其它语言编程的人一看就明白是怎么回事了

做个小题目:定义一个空的二维数组,将二维数组的值与索引一至

package main
import "fmt"
func main{
var arr_more [5][5]int
    fmt.Println(arr_more)
    for i, x := range arr_more {
        for i1, _ := range x {
            arr_more[i][i1] = i1
        }
    }
    fmt.Println(arr_more)
}

输出

初始化数组:
[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
值与索引对应
[[0 1 2 3 4] [0 1 2 3 4] [0 1 2 3 4] [0 1 2 3 4] [0 1 2 3 4]]

数组的处理还有很多别的形式,等着你在实际工作中的发现与总结

切片(slice)

切片是对数组一个连续片段的引用,它是一个引用类型,存储的是指针,所以在性能上比值数组更快,使用方法和数组基本类似,也可以通过索引进行访问,len()获得切片的长度,cap()获得切片最大的长度

切片声明格式

var 声明变量 []变量类型

和声明数组非常相似,切片的声明是不需要指定数组长度,因为切片的长度是可变的(等会介绍)

一个切片在初始化之前默认为nil,长度为0
一个相对完整的例子:

package main
import "fmt"
func main{
    var arr = [5]int{1, 2, 3, 4, 5}
    var slice []int
    fmt.Printf("初始化切片默认 %d\n", slice)
    var slice1 []int = arr[:]
    fmt.Printf("切片复制数组(简写) %d\n", slice1)
    var slice2 []int = arr[0:2]
    fmt.Printf("切片获得数组0-1的下标 %d\n", slice2)
    var slice3 []int = arr[2:5]
    fmt.Printf("切片获得数组2-4的下标 %d\n", slice3)
}

输出

初始化切片默认 []
切片复制数组(简写) [1 2 3 4 5]
切片获得数组0-1的下标 [1 2]
切片获得数组2-4的下标 [3 4 5]

上面的例子介绍了切片的初始化和获得数组中某一个片段的值,当然还有一些其他用法比如[:3],[3:]等等,切片的灵活性非常高,就看你需要什么数组的哪个片段

注意 绝对不要用指针指向 slice。切片本身已经是一个引用类型,所以它本身就是一个指针!!

用make()创建一个切片

当相关的数组还没有创建好的时候,我们可以用make()函数来创建一个切片,同时创建好相关联的数组

var slice []int = make([]type,len,cap)
var 切片变量 []切片类型 = make([]数组类型,数组长度,最大长度) cap是可选参数

通过一个例子来说明make的使用

package main
import "fmt"
func main() {
    var slice1 []int = make([]int, 5)
    for i := 0; i < len(slice1); i++ {
        slice1[i] = 5 * i
        fmt.Printf("Slice at %d is %d\n", i, slice1[i])
    }
    fmt.Printf("\nThe length of slice1 is %d\n", len(slice1))
    fmt.Printf("The capacity of slice1 is %d\n", cap(slice1))
}

输出

Slice at 0 is 0  
Slice at 1 is 5  
Slice at 2 is 10  
Slice at 3 is 15  
Slice at 4 is 20

The length of slice1 is 5  
The capacity of slice1 is 5  

make()函数在初始化切片是经常被使用的方式,当然你要用简单的var slice[]int = arr[:]也可以,看习惯

切片的复制与追加

通过copy()append()来进行操作
一个例子:

package main
import "fmt"
func main(){
sl_from := []int{1, 2, 3}
    sl_to := make([]int, 10)

    n1 := copy(sl_to, sl_from)
    fmt.Println(sl_to)
    fmt.Printf("Copied %d elements\n", n1) // n == 3

    sl3 := []int{1, 2, 3}
    sl3 = append(sl3, 4, 5, 6)
    fmt.Println(sl3)
}

输出:

[1 2 3 0 0 0 0 0 0 0]
Copied 3 elements
[1 2 3 4 5 6]

复制与增加需要注意的:

  1. 是将后面的元素或切片追加到前面
  2. 必须是相同的元素类型
  3. 当容量不足时,会生成一个新的地址来保证新增加的元素
  4. 如果上面的条件都满足,一般来说都会返回成功,除非内存耗尽了(无解)

小记:

当然切片还有更多的细节及处理方式,完整版最好还是去看官方提供的文档,本篇重点介绍了GO的数组与切片,下一篇将介绍GO的map类型

如果觉得文章能够对您有所帮助,可以关注我,你的支持会鼓励我不断分享更多更好的优质文章。

博客地址:https://www.astarblog.cn/index.php/2018/01/17/416.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 本文翻译自Rob Pike的文章《Arrays, slices (and strings): The mechan...
    大蟒传奇阅读 4,888评论 2 8
  • 出处---Go编程语言 欢迎来到 Go 编程语言指南。本指南涵盖了该语言的大部分重要特性 Go 语言的交互式简介,...
    Tuberose阅读 18,411评论 1 46
  • 风云无极空幽谷,茶佛缘斋,陌上花开,雾锁江寒水墨怀。 燕穿碧海心闲静,月下穿霾,万物宁皆,四季轮回玉华开。
    栩辰徉阅读 388评论 9 17
  • 再次踏上土地的感觉就像是找到了家,长途车坐的人身心俱疲,每次坐完长途车都暗暗发狠,再也不坐了。下一次还是会选择坐长...
    种太阳__嘟嘟阅读 457评论 0 0
  • 文/清一若水 皎白的月儿 你在遥远的天边 用明亮的目光 告诉我 最美的期许 是宁静的守护 冰洁的月儿 你在遥远的银...
    清一若水阅读 483评论 2 1