经过前两天我们学会了,Go基础的变量,常量, if-else, for, switch 控制语法结构. 那么今天我们将学会
- 数组 Array
- 切片 Slice
- Map 这应该叫 Key-Value 形式的键值对 比如 { "key": "val" }
- 数组和链表的区别和特点
- 三种结构的对比优缺点
- 什么时候使用哪种结构
- 底层实现及优化
- 思考和拓展
数组 Array
_数组_ 是一个固定长度的数列。
<code>package
mainimport
"fmt"
func
main
()
{var
a [5
]int
fmt.Println("emp:"
, a) a[4
] =100
fmt.Println("set:"
, a) fmt.Println("get:"
, a[4
]) fmt.Println("len:"
,len
(a)) b := [5
]int
{1
,2
,3
,4
,5
} fmt.Println("dcl:"
, b)var
twoD [2
][3
]int
for
i :=0
; i2
; i++ {for
j :=0
; j3
; j++ { twoD[i][j] = i + j } } fmt.Println("2d: "
, twoD) } /<code>
输出结果
<code>$
go
run
arrays.go
emp:
[0
0
0
0
0
]
set:
[0
0
0
0
100
]
get:
100
len:
5
dcl:
[1
2
3
4
5
]
2d:
[[0
1
2
]
[1
2
3
]]
/<code>
理解
var a [5]int 为数组定义. 大家一定要理解. 所谓数组就是连续的相同数据类型的一组数据. 比如这个是定义了一个连续内容5个int型的数组 默认值是0.
那么连续有什么好处呢? 当然学过c语言的或者java的都知道.连续的顺序查询快啊!
相对与数组 还有一种数据结构是链表. 就是node -> node ->node 类型的结构保存了下一个节点的指针.
数组和链表的区别和特点
数组的优点
- 随机访问性强
- 查找速度快
数组的缺点
- 插入和删除效率低
- 可能浪费内存
- 内存空间要求高,必须有足够的连续内存空间。
- 数组大小固定,不能动态拓展
链表的优点
- 插入删除速度快
- 内存利用率高,不会浪费内存
- 大小没有固定,拓展很灵活。
链表的缺点
- 不能随机查找,必须从第一个开始遍历,查找效率低
切片 Slice
增强版本数组 : slice 的类型仅由它所包含的元素决定(不像数组中还需要元素的个数)。要创建一个长度非零的空slice,需要使用内建的方法 make。这里我们创建了一个长度为3的 string 类型 slice(初始化为零值) 建议大家在go中采用
<code>package
mainimport
"fmt"
func
main
()
{ s :=make
([]string
,3
) fmt.Println("emp:"
, s) s[0
] ="a"
s[1
] ="b"
s[2
] ="c"
fmt.Println("set:"
, s) fmt.Println("get:"
, s[2
]) fmt.Println("len:"
,len
(s)) s =append
(s,"d"
) s =append
(s,"e"
,"f"
) fmt.Println("apd:"
, s) c :=make
([]string
,len
(s))copy
(c, s) fmt.Println("cpy:"
, c) l := s[2
:5
] fmt.Println("sl1:"
, l) l = s[:5
] fmt.Println("sl2:"
, l) l = s[2
:] fmt.Println("sl3:"
, l) t := []string
{"g"
,"h"
,"i"
} fmt.Println("dcl:"
, t) twoD :=make
([][]int
,3
)for
i :=0
; i3
; i++ { innerLen := i +1
twoD[i] =make
([]int
, innerLen)for
j :=0
; j < innerLen; j++ { twoD[i][j] = i + j } } fmt.Println("2d: "
, twoD) }/<code>
<code>$
go
run
slices.go
emp:
[
]
set:
[a
b
c]
get:
c
len:
3
apd:
[a
b
c
d
e
f]
cpy:
[a
b
c
d
e
f]
sl1:
[c
d
e]
sl2:
[a
b
c
d
e]
sl3:
[c
d
e
f]
dcl:
[g
h
i]
2d:
[[0]
[1
2
]
[2
3
4
]]
/<code>
Map
key : val 形式的一组 字典或者哈希. 不好翻译,直接采用map 称呼. 非常强大的
<code>package
mainimport
"fmt"
func
main
()
{ m :=make
(map
[string
]int
) m["k1"
] =7
m["k2"
] =13
fmt.Println("map:"
, m) v1 := m["k1"
] fmt.Println("v1: "
, v1) fmt.Println("len:"
,len
(m))delete
(m,"k2"
) fmt.Println("map:"
, m) _, prs := m["k2"
] fmt.Println("prs:"
, prs) n :=map
[string
]int
{"foo"
:1
,"bar"
:2
} fmt.Println("map:"
, n) }/<code>
<code>$go
run maps.go
map
:map
[k1:7
k2:13
] v1:7
len
:2
map
:map
[k1:7
] prs:false
map
:map
[foo:1
bar:2
]/<code>
三种结构的对比优缺点
当你需要一组序列的时候大多数采用slice, 当需要快速key 定位的时候采用Map O(1)就能找到. 速度极快, 实际工作中需要都采用. 想数组的化缺点是不能快速查询key.全部循环查询的化很费时间.
什么时候使用哪种结构
一般组合采用 向leetcode里面很多题目,可有将Slice转换成Map这样查找很快通过组合来提高程序运行效率
底层实现及优化
底层也是和C基本一样.建议大家看看slice 和map的源码包.官方源码包是开源的.可有理解的更加深刻.
本教程是对初学者.只要会使用,用熟练就可以了.
思考和拓展
数组和链表的区别.map 有什么好处