一.Go语言的数组
这边的样例子都有亲自跑过,之所以没有贴代码,图片显得比较直观点
Go语言数组的特点:
1. 可以通过_省略变量
2. 不仅range,任何地方都可以_来省略变量
3. [10]int 和 [20]int 是不同类型, 数组在函数中的传递,会拷贝数组
4. 在go语言一般不直接用数组
二. Go语言切片
概念:切片(slice)是对数组的一个连续片段的引用,所以切片是一个引用类型
切片特性:
- 取出的元素数量为:结束位置 - 开始位置;
- 取出元素不包含结束位置对应的索引,切片最后一个元素使用 slice[len(slice)] 获取;
- 当缺省开始位置时,表示从连续区域开头到结束位置;
- 当缺省结束位置时,表示从开始位置到整个连续区域末尾;
- 两者同时缺省时,与切片本身等效;
- 两者同时为 0 时,等效于空切片,一般用于切片复位
下面几个代码片段:
1.指定范围中生成切片 ==> slice [开始位置 : 结束位置]
// slice [开始位置 : 结束位置] 用法
var initArr = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
fmt.Println("array [2:6] = ", initArr[2:6]) // 输出结果(半包半闭):array [2:6] = [2 3 4 5]
fmt.Println("array [2:] = ", initArr[2:]) // 输出结果:array [2:] = [2 3 4 5 6 7]
fmt.Println("array [:6] = ", initArr[:6]) // 输出结果:array [:6] = [0 1 2 3 4 5]
fmt.Println("array [:] = ", initArr[:]) // 输出结果:array [:] = [0 1 2 3 4 5 6 7]
2.slice通过函数调用值的变化
注意:发现不管是初始的initArr,还是sliceArr对应的值都发生了改变,所以slice本身没有数据,是对底层array的一个view
func updateSlice(s []int) {
s[0] = 100
}
func main() {
// 第一段代码,slice通过函数修改完之后值的变化
sliceArr := initArr[:]
fmt.Println("sliceArr = ", sliceArr) // [0 1 2 3 4 5 6 7]
updateSlice(sliceArr)
fmt.Println("sliceArr = ", sliceArr) // [100 1 2 3 4 5 6 7]
fmt.Println("initArr = ", initArr) // [100 1 2 3 4 5 6 7]
sliceArr = initArr[2:]
fmt.Println("sliceArr = ", sliceArr) // [2 3 4 5 6 7]
updateSlice(sliceArr)
fmt.Println("initArr = ", initArr) // [100 1 100 3 4 5 6 7]
}
3.声明新的切片
- 切片是动态结构,只能与 nil 判定相等,不能互相判定相等。
- 声明但未使用的切片的默认值是 nil
// 声明新的切片
var newSliceInt []int
var newSliceString []string
var newSliceInitInt = []int{}
var sliceCreateByMake = make([]int, 10, 18) // 通过make来创建切片,第一个参数表示len,第二个参数cap
fmt.Println(newSliceInt, newSliceString, newSliceInitInt, sliceCreateByMake) // 输出的结果:[] [] []
fmt.Println(newSliceInt == nil) // 输出的结果:true
fmt.Println(newSliceString == nil) // 输出的结果:true
fmt.Println(newSliceInitInt == nil) // 输出的结果:false
4.slice的扩展
// 看这段代码段时候,是不是有个疑问:为什么s1只有到5,s2是基于s1得出段结果,确可以输出6
var initArr = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := initArr[2:6]
s2 := s1[3:5]
fmt.Println(s1, s2) // 输出结果:[2 3 4 5] [5 6]
fmt.Printf("s1=%v,len=%d,cap=%d \n", s1, len(s1), cap(s1)) // 输出结果:s1=[2 3 4 5],len=4,cap=6
fmt.Printf("s2=%v,len=%d,cap=%d \n", s2, len(s2), cap(s2)) // 输出结果:s2=[5 6],len=2,cap=3
原理:
- slice可以向后扩展,不可以向前扩展
- s[i]不可超越len(s),向后扩展不可超越底层数组cap(s)
5.slice(切片)的操作(增,删,改)
func main() {
// 看这段代码段时候,是不是有个疑问:为什么s1只有到5,s2是基于s1得出段结果,确可以输出6
var initArr = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := initArr[2:6]
s2 := s1[3:5]
// fmt.Println(s1, s2) // 输出结果:[2 3 4 5] [5 6]
fmt.Printf("s1=%v,len=%d,cap=%d \n", s1, len(s1), cap(s1)) // 输出结果:s1=[2 3 4 5],len=4,cap=6
fmt.Printf("s2=%v,len=%d,cap=%d \n", s2, len(s2), cap(s2)) // 输出结果:s2=[5 6],len=2,cap=3
// slice的添加
s3 := append(s2, 10) // [5 6 10] 这时候还是initArr的view,所以initArr打印出来的时候会有新增进去的10
s4 := append(s3, 17) // [5 6 10 17] 这时候就不是initArr的view,系统会默认创建个数组
s5 := append(s4, 25) // [5 6 10 17 25] 这时候就不是initArr的view,系统会默认创建个数组
fmt.Println(initArr) // [0 1 2 3 4 5 6 10]
// slice的复制
copy(s5, s1) // 我们将s1拷贝至s5,首先s5:[5 6 10 17 25], s1:[2 3 4 5]
fmt.Println(s5) // 输出结果:[2 3 4 5 25]
// slice的删除
s5 = append(s5[:2], s5[3:]...) // 初始值:[2 3 4 5 25],假如我们要删除s5第2个元素4
fmt.Println(s5) // 输出结果:[2 3 5 25]
}
- 添加元素时如果超越cap,系统会重新分配更大的数组
- slice添加元素的操作 s = append(s, value)
- 添加时候,如果cap容纳不下,cap 会在基础上* 2
- append添加数组的时候可以在后面加...
三.Go语言的MAP
// map的声明
m1 := map[string]string{
"name": "mk",
"age": "18",
"province": "fujian",
}
var m2 map[string]int // m2 == nil
m3 := make(map[string]int) // m3 == empty map
fmt.Println(m1, m2, m3)
// map的遍历
for k, v := range m1 {
fmt.Println(k, v)
}
// 获取元素
name, ok := m1["name"]
city, ok2 := m1["city"]
fmt.Println(name, ok) // 输出 mk true
fmt.Println(city, ok2) // 输出 false
// 删除元素
delete(m1, "name")
if name, ok := m1["name"]; ok {
fmt.Println(name, ok)
} else {
fmt.Println("don't exit") // 输出 don't exit
}
- key不存在的时候,会获取value的初始值
- 用value, ok := m[key]可以来判断是否存在该key
- 用delete来删除一个key
- 遍历的时候,不保证遍历顺序,如需,自己手动排序
- 除了slice,map,func的内建类型都可以做成key
- struct不包括上述类型,也可以做成key
四.Go语言的字符及字符处理
func main() {
chineseString := "I爱中国!"
fmt.Println(len(chineseString)) // 输出结果:11,每个中文占3个字节
for i, ch := range chineseString { // ch 就是rune ,四个字节
fmt.Printf("(%d)%X ", i, ch) // 输出结果:(0)49 (1)7231 (4)4E2D (7)56FD (10)21
}
fmt.Println(utf8.RuneCountInString(chineseString)) // 获取字符数量
for i, ch := range []rune(chineseString) {
fmt.Printf("%d%c ", i, ch)
}
}
- 使用range去遍历rune对
- 使用utf8.RuneCountInString可以获取字符数量
- 使用len获取字节的长度
- 使用[]byte获取字节