增加array、slice和map

This commit is contained in:
xiemengjun
2012-08-26 22:18:48 +08:00
parent 7624e35566
commit fc83016e34
7 changed files with 155 additions and 13 deletions

157
2.2.md
View File

@@ -168,12 +168,6 @@ GO中可以使用`+`来链接两个字符串
world`
`` ` `` 括起的字符串为Raw字符串即字符串在代码中的形式就是打印时的形式没有字符转义换行也将原样输出。
###GO数据底层的存储
下面这张图来源于 Russ Coxblog中的一篇介绍GO数据结构的文章大家可以看到这些基础类型底层都是开辟了一块内存然后存了相应的值
![](images/2.2.basic.png?raw=true)
###错误类型
Go内置有一个`error`类型专门用来处理错误信息GO的package里面还专门有一个包errors来处理错误
@@ -183,6 +177,12 @@ Go内置有一个`error`类型专门用来处理错误信息GO的package
fmt.Print(err)
}
###GO数据底层的存储
下面这张图来源于 Russ Cox blog中的一篇介绍GO数据结构的文章大家可以看到这些基础类型底层都是开辟了一块内存然后存了相应的值
![](images/2.2.basic.png?raw=true)
##一些技巧
###分组定义
@@ -249,12 +249,155 @@ array就是数组它的定义如下`[n]type`,n表示数组的长度type表
fmt.Printf("The first element is %d\n", arr[0]) //获取数据
由于数组的长度也是类型的一部分,比如`[3]int`与`[4]int`是不同的类型,所以数组是不能改变长度的,而且数组之间的赋值是值赋值,当把一个数组作为一个参数传入函数的时候,是这个数组的副本,而不是该数组的指针,如果要使用指针,那么就需要用到下面介绍的`slice`。
数组什么可以使用另一种`:=`来申明
a := [3]int{1,2,3} //申明一个长度为3的数组
b := [10]int{1,2,3} //申明了一个长度为10的数组其中前面三个元素初始化为1、2、3其他默认为0
c := […]int{4,5,6} //可以省略长度采用…go会自动计算长度
也许你会说我想数组里面还是数组能实现吗当然咯GO支持嵌套数组即多维数组如下代码申明了一个而二维数组
//申明了一个二维数组改数组是一个两个元素的数组然后每个元素里面是4个int的元素
double_array := [2][4]int {[4]int{1,2,3,4}, [4]int{5,6,7,8}}
//如果内部的元素和外部的一样,那么上面的申明可以简化,直接忽略内部的类型
easy_array :=[2][4]int{{1,2,3,4},{5,6,7,8}}
数组的分配如下所示:
![](images/2.2.array.png?raw=true)
###slice
我们很多的应用场景里面数组不能满足我们的需求因为我们不知道刚开始申明的时候到底需要多大的数组也就是我们需要动态数组GO里面我们叫做`slice`
`slice`并不是真正意义上面的动态数组,而是一个引用类型,`slice`总是指向底层的一个`array`。`slice`的申明也可以像`array`一样只要省略size
//和什么array一样只是少了长度
var fslice []int
接下来我们可以申明一个slice并初始化数据如下所示
slice := []byte {'a', 'b', 'c', 'd'}
slice可以从一个数组或者一个已经存在的slice里面再次申明`slice`通过array[i:j]来获取i是数组的开始位置j是结束位置但不包含array[j]他的长度是j-i
//申明一个含有是个字符元素的数组
var array [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
//申明两个含有byte的slice
var a_slice,b_slice,c_slice []byte
//a_slice指向数组的第2个元素开始并到第五个元素结束
a_slice = array[2:5]
//现在a_slice含有的元素: array[2], array[3] and array[4]
// b_slice是另一个数组的slice.
b_slice = array[3:5]
// b_slice的元素是: array[3], array[4]
他们的数据结构如下所示
![](images/2.2.slice.png?raw=true)
slice有一些简便的操作
- slice的默认开始位置是0ar[:n]等价于ar[0:n]
- slice的第二个序列默认是数组的长度ar[n:]等价于ar[n:len(ar)]
- slice如果从一个数组里面直接获取可以这样ar[:]因为默认第一个序列是0第二个是数组的长度即等价于ar[0,len(ar)]
下面这个例子展示更多关于slice的操作
//申明一个数组
var array [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
//什么两个slice
var a_slice,b_slice []byte
// 演示一些简便操作
a_slice = array[:3] // 等价于a_slice = array[0:3] a_slice包含元素: a,b,c
a_slice = array[5:] // 等价于a_slice = array[5:9] a_slice包含元素: f,g,h,i,j
a_slice = array[:] // 等价于a_slice = array[0:9] 这样a_slice包含了全部的元素
//从slice获取slice
a_slice = array[3:7] // a_slice包含元素: d,e,f,g
b_slice = a_slice[1:3] //b_slice 包含a_slice[1], a_slice[2] 也就是含有: e,f
b_slice = a_slice[:3] //b_slice 包含 a_slice[0], a_slice[1], a_slice[2] 也就是含有: d,e,f
b_slice : a_slice[:] //b_slice包含所有a_slice的元素: d,e,f,g
slice是引用类型所以当引用改变值的时候那么其他的所有引用都会改变该值例如上面的a_slice和b_slice如果修改了a_slice的值那么b_slice相对应的值也会改变。
从概念上面来说slice想一个结构体这个结构体包含了三个元素
- 一个指针指向数组中slice指定的开始位置
- 长度slice的长度
- 最大长度也就是slice开始位置到数组的最后位置的长度
array := [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
slice := A[4:8]
上面代码的真正存储结构如下图所示
![](images/2.2.slice2.png?raw=true)
slice下面有几个有用的内置函数
- len 获取slice的长度
- cap 获取slice的最大容量
- append 向slice里面追加一个或者多个元素然后返回一个和slice一样类型的slice
- copy 函数copy 从源slice src 复制元素到目标dst并且返回复制的元素的个数
###map
map也就是python中字典的概念它的格式`map[keyType]valueType`
我们看下面的代码map的读取和设置也类似slice一样通过来key操作只是slice只有int的key而map多了很多类型可以是int可以是string
// 申明一个key是字符串值为int的字典
var numbers map[string] int
//另一种map的什么方式
numbers = make(map[string]int)
numbers["one"] = 1 //赋值
numbers["ten"] = 10 //赋值
numbers["three"] = 3
fmt.Println("第三个数字是: ", numbers[3]) //读取数据
// 打印出来如下:
//第三个数字是: 3
这个map就像我们平常看到的表格一样左边列是key右边列是值
使用map过程中需要注意的几点
- map是无序的每次打印出来的map都会不一样,他不能通过index获取而必须通过key获取
- map的长度是不固定的也就是和slice一样也是一种引用类型
- 内置的len函数同样试用于map返回map拥有的key的数量
- map的值可以很方便的修改通过`numbers["one"]=11`可以很容易的把key为`one`的字典值改为11
map的初始化可以通过key:val的方式初始化值同时获取map内置有判断是否存在key的方式
删除map的元素通过delete
//初始化一个字典
rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
//map可以有两个返回值第二个返回值如果不存在key那么ok为false如果存在ok为true
csharp_rating, ok := rating["C#"]
if ok {
fmt.Println("C# is in the map and its rating is ", csharp_rating)
} else {
fmt.Println("We have no rating associated with C# in the map")
}
delete rating["C"] //删除key为C的元素
上面说过了map也是一种引用类型如果两个map同时指向一个底层那么一个改变另一个也相应的改变
m = make(map[string][string])
m["Hello"] = "Bonjour"
m1 = m
m1["Hello"] = "Salut" //现在m["hello"]的值已经是Salut了

11
2.md
View File

@@ -4,12 +4,11 @@
* 1. [你好GO](2.1.md)
* 2. [GO基础](2.2.md)
* 3. [流程和函数](2.3.md)
* 4. [混合类型](2.4.md)
* 5. [高级类型](2.5.md)
* 6. [面向对象](2.6.md)
* 7. [并发](2.7.md)
* 8. [通讯](2.8.md)
* 9. [小结](2.9.md)
* 4. [高级类型](2.4.md)
* 5. [面向对象](2.5.md)
* 6. [并发](2.6.md)
* 7. [通讯](2.7.md)
* 8. [小结](2.8.md)
GO是一门类似C的编译性语言但是他的编译速度非常快这门语言的关键字加起来也就二十五个比英文字母的二十六还少一个这对于我们来说是学习就变得简单了很多先让我们看一眼这写关键字都长成怎么样

BIN
images/.DS_Store vendored Normal file

Binary file not shown.

BIN
images/2.2.array.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
images/2.2.makenew.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
images/2.2.slice.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
images/2.2.slice2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB