数组

数组是一组固定长度的序列

数组类型

数组的类型不仅和储存元素的类型有关,还和数组长度有关,不同长度的数组是不同的类型

不同类型的数组不能共用一个函数

func main() {
var a [10]int
var b [5]int
var c [5]int32
fmt.Printf("type a: %T,\ntype b: %T,\ntype c: %T", a, b, c)
}

储存数据

由于数组中储存的是值,所以直接传入函数中无法改变原来的值,需要传入地址才能修改原来的值

传值

示例:

func change(a [5]int){
fmt.Println("in change, before change", a)
a[0] = 100
fmt.Println("in change, after change", a)
} func toChange() {
a := [5]int{0, 0, 0, 0, 0}
fmt.Println("in main, before change", a)
change(a)
fmt.Println("in main. after change", a)
}

输出结果:

in main, before change [0 0 0 0 0]
in change, before change [0 0 0 0 0]
in change, after change [100 0 0 0 0]
in main. after change [0 0 0 0 0]

main 中数组并没有改变

传引用

示例:

func change(a *[5]int){
fmt.Println("in change, before change", *a)
a[0] = 100
fmt.Println("in change, after change", *a)
} func main() {
a := [5]int{0, 0, 0, 0, 0}
fmt.Println("in main, before change", a)
change(&a)
fmt.Println("in main. after change", a)
}

输出结果:

in main, before change [0 0 0 0 0]
in change, before change [0 0 0 0 0]
in change, after change [100 0 0 0 0]
in main. after change [100 0 0 0 0]

main 中数组发生改变

数组初始化

在数组未进行初始化时,所有的元素都是默认值

// 标准初始化
var array [5]int = [5]int{1, 2, 3, 4, 5} // 省略类型,会自动判断数组长度与元素类型
var array = [5]int{1, 2, 3, 4, 5} // 省略长度,会自动判断初始化元素个数来确定长度
var array = [...]int{1, 2, 3, 4, 5} // 指定索引初始化
var array = [5]int{0: 3, 4: 3}

切片

切片时数组的一个引用,是引用类型

切片长度可变

切片的结构

切片内部储存的只有指向相应数组对应元素的指针和切片的长度、容量

package main

import "fmt"

func main() {
var array = [5]int{1, 2, 3, 4, 5}
var slice = array[2:]
fmt.Printf("array: %p slice: %p\n", &array[2], slice)
}

输出结果:

array: 0xc00001a160 slice: 0xc00001a160

切片从 array[2] 开始,所以指向的就是 array[2]

切片定义

var slice[]int

切片初始化

切片初始化的时候可以自己创建一个数组进行初始化,也可以用 make 进行初始化,但是 make 实际上也是创建了一个数组

// 通过数组初始化
var slice[]int = array[start: end] // 通过 make 初始化
var slice = make([]int, len)
var slice = make([]int, len, cap)

append

append 用于在切片后面添加元素

用法

// 切片后添加元素
slice = append(slice, elems) // 切片后添加切片
// slice... 用来将 slice 展开
slice = append(slice, slice...)

实现

由于切片是基于数组的,但是数组的长度不可变,所以进行 append 操作时,

如果内存空间不足:切片会新开辟一段内存空间由于存储新数组,每次开辟都是原来数组长度的两倍

如果内存空间够用:切片会使用原来数组的内存,修改数组中原来的元素

开辟空间示例:

func main() {
var array = [10]int{}
var slice = array[:]
fmt.Printf("slice %p len: %d\n", slice, len(slice))
slice = append(slice, 2)
fmt.Printf("slice %p len: %d(should change)\n", slice, len(slice))
slice = append(slice, slice[:len(slice) - 2]...)
fmt.Printf("slice %p len: %d(should not change)\n", slice, len(slice))
slice = append(slice, 1)
fmt.Printf("slice %p len: %d(should change)\n", slice, len(slice))
}

输出结果:

slice 0xc00001e050 len: 10
slice 0xc0000140a0 len: 11(should change)
slice 0xc0000140a0 len: 20(should not change)
slice 0xc00008c000 len: 21(should change)

初始数组长度为 10,

append 1 个元素之后,长度为 11,由于超过数组最大长度,所以需要开辟新的内存空间,长度为 20,切片指向的地址发生改变

append 9 个元素之后,长度为 20,由于没有超过数组最大长度,所以指向不变

append 1 个元素之后,长度为 21,由于超过数组最大长度,所以需要开辟新的内存空间,长度为 40,切片指向的地址发生改变

修改数组示例:

func main() {
var array = [10]int{8: 1}
var slice = array[: 8]
fmt.Printf("slice %p len: %d\n", slice, len(slice))
fmt.Printf("array: %v\n", array)
slice = append(slice, 2)
fmt.Printf("slice %p len: %d(should not change)\n", slice, len(slice))
fmt.Printf("array: %v\n", array)
slice = append(slice, 2)
fmt.Printf("slice %p len: %d(should not change)\n", slice, len(slice))
fmt.Printf("array: %v\n", array)
slice = append(slice, 2)
fmt.Printf("slice %p len: %d(should change)\n", slice, len(slice))
fmt.Printf("array: %v\n", array)
}

输出结果:

slice 0xc00001e050 len: 8
array: [0 0 0 0 0 0 0 0 1 0]
slice 0xc00001e050 len: 9(should not change)
array: [0 0 0 0 0 0 0 0 2 0]
slice 0xc00001e050 len: 10(should not change)
array: [0 0 0 0 0 0 0 0 2 2]
slice 0xc0000140a0 len: 11(should change)
array: [0 0 0 0 0 0 0 0 2 2]

初始数组长度为 10,但是切片切了前 8 个元素

append 的元素未超过数组本身的长度时,会直接修改数组中原来的元素,如果超过了,则开辟新的内存

copy

copy 用来复制切片

如果被复制的切片元素不足,多余部分不变

如果被复制的切片元素超出目标切片长度(与容量无关),则忽略超出部分

用法:

// 切片 dst 变为 切片 scr 的复制
copy(dst []Type, src []Type)

示例:

func main(){
a := []int{1, 2, 3, 4, 5}
b := make([]int, 3, 4)
fmt.Printf("b: %v, a: %v\n", b, a)
copy(b, a)
fmt.Printf("b: %v, cap: %d, prt: %p\n", b, cap(b), b)
b = append(b, 1)
fmt.Printf("b: %v, cap: %d, prt: %p\n", b, cap(b), b)
copy(b, a)
fmt.Printf("b: %v, a: %v\n", b, a)
}

输出结果:

b: [0 0 0], a: [1 2 3 4 5]
b: [1 2 3], cap: 4, prt: 0xc000018140
b: [1 2 3 1], cap: 4, prt: 0xc000018140
b: [1 2 3 4], a: [1 2 3 4 5]

string

字符串 (string) 就是 bytes 组成的不可变的集合

关于字符串类型 <- 点击查看

Go 数组(array) & 切片(slice)的更多相关文章

  1. 转对象(含length属性)成数组Array.prototype.slice.call(arguments)

    我们知道,Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组,除了IE下的节点集合(因为ie下的dom对象是以com对象的形式实现的,js ...

  2. 类数组转数组Array.prototype.slice.call(arrayLike)

    转换方式:Array.prototype.slice.call(arrayLike) 附:(http://www.jianshu.com/p/f8466e83cef0) 首先Array.prototy ...

  3. JS的数组进行切片slice

    代码 var arr = new Array(6) arr[0] = "George" arr[1] = "John" arr[2] = "Thoma ...

  4. Go通关04:正确使用 array、slice 和 map!

    Array(数组) 数组存放的是固定长度.相同类型的数据. 数组声明 var <数组名> = [<长度>]<元素>{元素1,元素2} var arr = [2]in ...

  5. (66)Wangdao.com第十一天_JavaScript 数组Array

    数组 Array 本质上,数组属于一种特殊的对象.typeof 运算符会返回数组的类型是 object 数组的特殊性体现在,它的键名是按次序排列的一组整数(0,1,2...) // Object.ke ...

  6. Golang 数组、切片、映射

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

  7. JavaScript中的Array.prototype.slice.call()方法学习

    JavaScript中的Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性). 但有一个例外 ...

  8. go 数组(array)、切片(slice)、map、结构体(struct)

    一 数组(array) go语言中的数组是固定长度的.使用前必须指定数组长度. go语言中数组是值类型.如果将数组赋值给另一个数组或者方法中参数使用都是复制一份,方法中使用可以使用指针传递地址. 声明 ...

  9. Go - 数组 和 切片(array、slice)

    一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建 数组有 3 种创建方式: 1) [length]Type 2) [length]Type{value ...

随机推荐

  1. python中bitmap的参数

    Tkinter Bitmaps: 你会使用这个属性显示一个位图.有以下类型的可用位图. 你会使用这个属性显示一个位图.有以下类型的可用位图.: "error" "gray ...

  2. 一线大厂面试官最喜欢问的15道Java多线程面试题

    前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得更多职位,那么你应该准备很多关于多线程的问题. 他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者 ...

  3. sleep方法要求处理中断异常:InterruptedException

    package seday08.thread;/*** @author xingsir * 当一个线程调用sleep方法处于阻塞状态的过程中,这个线程的中断方法interrupt被调用时,则sleep ...

  4. JS---案例:完整的轮播图---重点!

    案例:完整的轮播图 思路: 分5部分做 1. 获取所有要用的元素 2. 做小按钮,点击移动图标部分 3. 做右边焦点按钮,点击移动图片,小按钮颜色一起跟着变 (克隆了第一图到第六图,用索引liObj. ...

  5. FCC---CSS Flexbox: Apply the flex-direction Property to Create a Column in the Tweet Embed

    The tweet embed header and footer used the flex-direction property earlier with a row value. Similar ...

  6. Django:永别了pycrypto库~

    在开发微信登陆功能时,解密用户信息需要使用到 Crypto 包,所以安装了pycrypto库. Linux.OS X 系统均可直接 pip install pycrypto . 最近换到win10下开 ...

  7. 安卓AlertDialog四种对话框的最科学编写用法

    首先我们上图: xml的代码如下,用于编写按钮: <?xml version="1.0" encoding="utf-8"?> <Linear ...

  8. Csharp:HttpWebRequest or HttpClient

    /// <summary> /// Define other methods and classes here /// </summary> /// <param nam ...

  9. Appium(五):Desired Capabilities

    1. Desired Capabilities Desired Capabilities简单来说就是一组设置,这些设置可以让测试脚本控制Appium的运行行为.下面就逐个对Desired Capabi ...

  10. SpringCloud断路器(Hystrix)

    一.为什么需要 Hystrix? 在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用(RPC).为了保证其高可用,单个服务又必须集群部署.由于网络原因或者自身的原因,服务并不能保 ...