文章目录

  • 数组
  • 切片(Slice)
  • 键值对(Map)
  • 字符和字符串处理
    • strings包中的各种操作方法;
      • Fields,Split,Join
      • Contains,Index
      • ToLower, ToUpper
      • Trim,TrimRight,TrimLeft

数组

  • 数组的空间大小写在类型前;
  • 除常规遍历数组方法之外,还可以通过range关键字进行遍历;
  • 可通过 _ 省略变量,不仅仅在range中,任何地方都可以通过 _ 省略变量;
  • 数组是值类型,调用 func f(arr [10] int)会拷贝数组;
  • 数组是作为函数参数时是值类型,即拷贝;其他语言中获取数组名即获取数组的首元素地址,是引用传递;
  • [10] int 和[20] int是不同的数据类型;
  • Go中一般不直接使用数组。
  1. 数组定义
  • 数组定义的案例
var arr1 [5]int // 这里仅仅定义为对数组初始化,但go给数组每个元素赋值默认值0arr2 := [3]int{1, 3, 5} // 使用:=定义时必须进行初始化arr3 := [...]int{2, 4, 6, 8, 10} // 数组欺骗var grid [4][5]bool // 多维数组fmt.Println(arr1, arr2, arr3)
fmt.Println(grid)

输出结果:

[0 0 0 0 0] [1 3 5] [2 4 6 8 10]
[[false false false false false] [false false false false false] [false false false false false] [false false false false false]]
  1. 数组遍历
  • 数组遍历的案例
// 遍历方法一 使用range关键字
for i := range arr3 {  // 关键字range获得数组arr3的下标fmt.Println(arr3[i])
}
//关于range另外写法
for i, v := range arr3 {// 关键字range同时获得数组arr3的下标和对应的元素值// 若不想写变量i,可以用_替代ifmt.Println(i, v)  // 输出下标以及元素值
}// 遍历方法二
for i := 0; i < len(arr2); i++ {fmt.Println(arr2[i])
}
  1. 数组参数传递

数组参数传递的案例

// 值传递
func printArray1(arr [5]int){arr[0] = 100 // 验证数组是值传递而非引用传递for i, v := range arr {fmt.Println(i, v)}
}// 引用传递,借用指针
func printArray2(arr *[5]int){arr[0] = 100 // 验证数组是值传递而非引用传递for i, v := range arr {fmt.Println(i, v)}
}func main() {var arr1 [5]int // 这里仅仅定义为对数组初始化,但go给数组每个元素赋值默认值0arr2 := [3]int{1, 3, 5} // 使用:=定义时必须进行初始化arr3 := [...]int{2, 4, 6, 8, 10}fmt.Println("--------------值传递")fmt.Println("printArray1(arr1)")printArray1(arr1) // 可行fmt.Println("printArray1(arr3)")printArray1(arr3) // 可行// printArray1(arr2) // 不可行fmt.Println("arr1 and arr3")fmt.Println(arr1, arr3)fmt.Println("-------------引用传递")fmt.Println("printArray2(&arr1)")printArray2(&arr1) // 取地址fmt.Println("printArray2(&arr3)")printArray2(&arr3)fmt.Println("arr1 and arr3")fmt.Println(arr1, arr3) // 数组的第一个元素被改为100
}

输出结果:

--------------值传递
printArray_value(arr1)
0 100
1 0
2 0
3 0
4 0
printArray_value(arr3)
0 100
1 4
2 6
3 8
4 10
arr1 and arr3
[0 0 0 0 0] [2 4 6 8 10]  // 第一个元素没有变成100
-------------引用传递
printArray_reference(&arr1)
0 100
1 0
2 0
3 0
4 0
printArray_reference(&arr3)
0 100
1 4
2 6
3 8
4 10
arr1 and arr3
[100 0 0 0 0] [100 4 6 8 10] // 第一个元素变成100


为什么要使用range

  1. 意义明确,美观
  2. c++:没有类似能力
  3. Java/Python:只能for each value,不能同时获取i, v

切片(Slice)

  1. 切片的定义
  • slice本身没有数据,是对底层array的一个view;

  • slice是引用类型,是数组array的引用,是动态数组;

  • 切片的定义的案例

func main() {arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8}fmt.Println("arr[2:6] = ", arr[2:6]) // slice是引用类型,是数组的引用,是动态数组fmt.Println("arr[:6] = ", arr[:6])fmt.Println("arr[2:] = ", arr[2:])fmt.Println("arr[:] = ", arr[:]) // arr[:] 和 arr不同;arr[:]是切片,动态数组,而arr仅仅是数组
}

输出结果:

arr[2:6] =  [2 3 4 5]
arr[:6] =  [0 1 2 3 4 5]
arr[2:] =  [2 3 4 5 6 7 8]
arr[:] =  [0 1 2 3 4 5 6 7 8]
  1. 切片的引用传递
  • 切片的引用传递的案例
func updateSlice(s []int) { // 不带长度的,表示Slices[0] = 100
}func main() {arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8}fmt.Println("-------slice")s1 := arr[2:]fmt.Println("s1 : ", s1)s2 := arr[:]fmt.Println("s2 : ", s2)// 切片是引用传递的fmt.Println("After updateSlice(s1)")updateSlice(s1)fmt.Println(s1)fmt.Println(arr)fmt.Println("After updateSlice(s2)")updateSlice(s2)fmt.Println(s2)fmt.Println(arr)
}

输出结果:

-------slice
s1 :  [2 3 4 5 6 7 8]
s2 :  [0 1 2 3 4 5 6 7 8]
After updateSlice(s1)
[100 3 4 5 6 7 8]
[0 1 100 3 4 5 6 7 8]
After updateSlice(s2)
[100 1 100 3 4 5 6 7 8]
[100 1 100 3 4 5 6 7 8]
  1. 切片自切
  • 切片自切的案例
func main() {arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8}s2 := arr[:]fmt.Println("Reslice") // 自切fmt.Println(s2)s2 = s2[:5]fmt.Println(s2)s2 = s2[2:]fmt.Println(s2)
}

输出结果

Reslice
[0 1 2 3 4 5 6 7 8]
[0 1 2 3 4]
[2 3 4]
  1. 切片扩展
  • slice可以向后扩展,不可以向前扩展;

  • 切片的长度len是它所包含的元素个数。

  • 切片的容量cap是从它的第一个元素开始数,到其底层数组元素末尾的个数

  • s[i]不可以超越len(s),向后扩展可以超越len(s)但不可以超越底层数组cap(s),如下例;

  • 切片扩展的案例

func main(){fmt.Println("Extending slice") // slice 的扩展arr1 := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8}s1 = arr1[2:6] // s1中有4个元素,但切片扩展的元素的个数为4+3(隐藏的元素个数)=7个s2 = s1[3:6]  // [ s1[3], s1[4], s1[5] ]  向后扩展了// var _ int = s1[4] // 报错,数组下标越界  runtime error: index out of range [4] with length 4// 切片能读取后面隐藏的元素即扩展元素,数组不能读取到隐藏的元素fmt.Printf("arr1 = %v, len(arr1) = %d\n", arr1, len(arr1))fmt.Printf("s1 = %v, len(s1) = %d, cap(s1) = %d\n", s1, len(s1), cap(s1))fmt.Printf("s2 = %v, len(s2) = %d, cap(s2) = %d\n", s2, len(s2), cap(s2))
}

输出结果:

Extending slice
arr1 = [0 1 2 3 4 5 6 7 8], len(arr1) = 9
s1 = [2 3 4 5], len(s1) = 4, cap(s1) = 7
s2 = [5 6 7], len(s2) = 3, cap(s2) = 4
  1. Slice的创建
  • 创建方法一:同定义未初始化的数组一样但不写明长度

  • 创建方法二:同边定义边初始化的数组一样但不写明长度

  • 创建方法三:使用 make() 定义Slice

  • 创建Slice的案例

func printSlices(s []int)  {fmt.Printf("%v, len = %d, cap = %d\n",s, len(s), cap(s))
}
func main()  {fmt.Println("Create Slice")// 创建方法一var s []int // Zero value for slice is nil// 此时 s == nillfor i := 0; i < 100; i++{printSlices(s)s = append(s, 2 * i + 1)}fmt.Println(s)fmt.Println("--------------")// 创建方法二s1 := []int{2, 4, 6, 8}  // len = 4,  cap = 4printSlices(s1)// 创建方法三s2 := make([]int, 15) // len = 15, cap = 15s3 := make([]int, 10, 32) // len = 10, cap = 32// s2,  s3为初始化,都赋值默认值0printSlices(s2)printSlices(s3)
}

部分输出结果:

...
--------------
[2 4 6 8], len = 4, cap = 4
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len = 15, cap = 15
[0 0 0 0 0 0 0 0 0 0], len = 10, cap = 32
  1. 向Slice添加元素
  • 添加元素时如果超越cap,系统会重新分配更大的底层数组;

  • 又要值传递的关系,必须接受append的返回值;

  • s = append(s, val)

  • 添加元素

func main(){arr1 := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8}s1 = arr1[2:6]s2 = s1[3:6]s3 := append(s2, 10)s4 := append(s3, 11)s5 := append(s4, 12)fmt.Println("s3, s4, s5 = ", s3, s4, s5)// s4 and s5 no longer view arr1fmt.Println("arr1 = ", arr1)
}

输出结果:

append slice
s3, s4, s5 =  [5 6 7 10] [5 6 7 10 11] [5 6 7 10 11 12]
arr1 =  [0 1 2 3 4 5 6 7 10]
// 其中s4, s5的底层数组不知道在哪里


向Slice进行append操作时,可能需要更换新底层数组,从而导致Slice的ptr,len,cap都变更,需要新的Slice来接受这三个值;

  1. Slice的复制
  • 通过系统内建函数 copy() 来实现。

  • Slice复制的案例

func main(){s1 := []int{2, 4, 6, 8}s2 := make([]int, 15)printSlices(s1)printSlices(s2)fmt.Println("Copying slice")copy(s2, s1)  // 将s1复制到s2上printSlices(s2)
}

输出结果:

[2 4 6 8], len = 4, cap = 4
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len = 15, cap = 15
Copying slice
[2 4 6 8 0 0 0 0 0 0 0 0 0 0 0], len = 15, cap = 15
  1. Slice元素的删除
  • Go中无内建删除函数;

  • 利用append()函数进行删除操作;

  • s = append(s[:index], s[index+1:]…);

  • Slice元素的删除的案例

func main(){s1 := []int{2, 4, 6, 8}s2 := make([]int, 15)copy(s2, s1) printSlices(s2)fmt.Println("Deleting elements from  slice")// 删除下标为3的元素s2 = append(s2[:3], s2[4:]...) // append的第二个参数是可变参数printSlices(s2)// 删除切片首元素fmt.Println("Popping from front")font := s2[0]s2 = s2[1:]fmt.Println("front = ", font)printSlices(s2)// 删除切片尾元素fmt.Println("Popping from  back")back := s2[len(s2) - 1]s2 = s2[:len(s2) - 1]fmt.Println("back = ",back)printSlices(s2)
}

输出结果:

[2 4 6 8 0 0 0 0 0 0 0 0 0 0 0], len = 15, cap = 15
Deleting elements from  slice
[2 4 6 0 0 0 0 0 0 0 0 0 0 0], len = 14, cap = 15
Popping from front
front =  2
[4 6 0 0 0 0 0 0 0 0 0 0 0], len = 13, cap = 14
Popping from  back
back = 0
[4 6 0 0 0 0 0 0 0 0 0 0], len = 12, cap = 14


cap表示是slice中ptr到底部数组最后一个元素之间元素个数
利用append删除中间元素时,底部数组并没有改变,故cap=15,由于少一个元素,长度len=14;
删除slice的首元素,需要slice的ptr向后移动一位,故cap=14,由于少一个元素,长度len=13;
删除slice的尾元素,没有影响ptr,以及底部数组不变,故cap=14,由于少一个元素,长度len=12;
上述过程中s2的物理地址没有发送变化

键值对(Map)

  • Map的结构:map[K]V,键为K 值为V;
  • Map的复合结构:map[K1]map[K2]V, 外面的map的 键为K1 值为map,里面的map的 键为K2 值为V;
  1. Map创建
  • 创建方式一:map [ 键类型 ] 值类型 { “键名” : “值” }
  • 创建方式二:make ( map [ 键类型 ] 值类型 )
  • 创建方法三:var Map名 map [ 键类型 ] 值类型
  • 创建案例
func main(){// map构建方法一m := map[string]string {"name" : "ccmouse","course" : "Golang","sit" : "immoc","quality" : "notbad",}fmt.Println(m)// map构建方法二m2 := make(map[string]int)  // 空的,未初始化 m2 == emptyfmt.Println(m2)// map构建方法三var m3 map[string]int // m3 == nilfmt.Println(m3)
}

输出结果:

map[course:Golang name:ccmouse quality:notbad sit:immoc]
map[]
map[]
  1. Map的遍历
  • 使用range遍历key,或者遍历key,value对;
  • 不保证遍历顺序,如需顺序,需要手动对key排序;
  • map中的元素是无序的, 每次遍历顺序是不一样;
  • 使用len获得map的元素个数;
  • map使用哈希表,必须可以比较相等;
  • 除了slice,map,function的内建类型都可以作为key;
  • 自定义类型Struct不包含上述字段,也可作为key;
  • 遍历案例
func main(){m := map[string]string {"name" : "ccmouse","course" : "Golang","sit" : "immoc","quality" : "notbad",}// map遍历fmt.Println("------Traversing map------")for k, v := range m {fmt.Println(k, v)}// 只要kfmt.Println("------Only need K------")for k := range m {fmt.Println(k)}// 只要vfmt.Println("------Only need V------")for _, v := range m {fmt.Println(v)}// 每次遍历顺序不一样,map中的元素是无序的
}

输出结果:

------Traversing map------
name ccmouse
course Golang
sit immoc
quality notbad
------Only need K------
sit
quality
name
course
------Only need V------
ccmouse
Golang
immoc
notbad
  1. 获得Map中的元素
  • 获取元素:m [ key ]
  • key不存在时,获得Value类型的初始值
  • 通过键获取对应值的案例
func main(){m := map[string]string {"name" : "ccmouse","course" : "Golang","sit" : "immoc","quality" : "notbad",}fmt.Println("------Getting values------")courseName := m["course"]fmt.Println(courseName)causeName := m["cause"] // m中不存在cause键fmt.Println(causeName) // 获取不存在键对应的值时,输出结果是空的,这里是空串
}

输出结果:

------Getting values------
Golang
  • 用value, ok := m [ key ] 来判断是否存在key
  • 判断元素是否存在map的案例
func main(){m := map[string]string {"name" : "ccmouse","course" : "Golang","sit" : "immoc","quality" : "notbad",}// 判断k是否在map中if caseName, ok := m["case"]; ok { // m中不存在casefmt.Println(caseName)}else {fmt.Println("key does not exist")}
}

输出结果:

key does not exist
  1. 删除map中的元素
func main(){m := map[string]string {"name" : "ccmouse","course" : "Golang","sit" : "immoc","quality" : "notbad",}// 删除map中的元素,使用内建函数delete()fmt.Println("------Deleting values------")name, ok := m["name"]fmt.Println(name, ok)delete(m, "name")name, ok = m["name"]fmt.Println(name, ok)
}

输出结果:

------Deleting values------
ccmouse truefalse

字符和字符串处理

  • 使用range遍历pos,rune对;
  • 使用utf8.RuneCountInString获得字符数量;
  • len(string)只是获得字节数
  • 使用[]byte获得字节;
  • byte转为rune就不需要考虑UTF-8编码问题;
  • 字符串处理案例
func main() {s := "Yes我爱慕课网!"fmt.Println(len(s))for _, b := range []byte(s) {fmt.Printf("%X ", b)}fmt.Println()// UTF-8 可变长//一个英文占一个字节,一个中文占三个字节for i, ch :=  range s {  // ch is a rune 四字节的int型(int32)// UTF-8转为Unicodefmt.Printf("(%d, %X) ", i, ch)}fmt.Println()fmt.Println("Rune count:",utf8.RuneCountInString(s))bytes := []byte(s)for len(bytes) > 0 {ch, size := utf8.DecodeRune(bytes) // 英文字符的size是1,中文的字符size是3bytes = bytes[size:]fmt.Printf("%c ", ch)}fmt.Println()// 将字符串转runefor i, ch := range []rune(s) {// 重新开了一个rune数组fmt.Printf("(%d %c) ", i, ch)}fmt.Println()
}

输出结果:

19
59 65 73 E6 88 91 E7 88 B1 E6 85 95 E8 AF BE E7 BD 91 21
(0, 59) (1, 65) (2, 73) (3, 6211) (6, 7231) (9, 6155) (12, 8BFE) (15, 7F51) (18, 21)
Rune count: 9
Y e s 我 爱 慕 课 网 !
(0 Y) (1 e) (2 s) (3 我) (4 爱) (5 慕) (6 课) (7 网) (8 !)

strings包中的各种操作方法;

Fields,Split,Join
  1. Fields 空格分割
func Fields (s string) []string
  • 返回将字符串按照空格(连续的空格被认为一个空格进行分割)分割的多个字符串。如果字符串全部是空格或者是空字符串的话,会返回空切片。
  • example
fmt.Printf("Fields are: %q", strings.Fields("  foo bar  baz   "))
  • output
Fields are: ["foo" "bar" "baz"]
  1. Split 以sep为分割符分割
func Split(s, sep string) []string
  • 以指定的分隔符拆分,返回一组切片;

  • 去掉s中出现的sep的方式进行分割,会分割到结尾,并返回生成的所有片段组成的切片(每一个sep都会进行一次切割,即使两个sep相邻,也会进行两次切割)。如果sep为空字符,Split会将s切分成每一个unicode码值一个字符串。

  • example

fmt.Printf("%q\n", strings.Split("a,b,c", ","))
fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))
fmt.Printf("%q\n", strings.Split(" xyz ", ""))
fmt.Printf("%q\n", strings.Split("", "Bernardo O'Higgins"))
  • output
["a" "b" "c"]
["" "man " "plan " "canal panama"]
[" " "x" "y" "z" " "]
[""]
  1. Join连接
func Join(a []string, sep string) string
  • 将一系列字符串连接为一个字符串,之间用sep来分隔;
  • example
s := []string{"foo", "bar", "baz"}
fmt.Println(strings.Join(s, ", "))
  • output
foo, bar, baz
Contains,Index
  1. Contains判断是否包含子串
func Contains(s, substr string) bool
  • 判断字符串s是否包含子串substr。
  • exmaple
fmt.Println(strings.Contains("seafood", "foo"))
fmt.Println(strings.Contains("seafood", "bar"))
fmt.Println(strings.Contains("seafood", ""))
fmt.Println(strings.Contains("", ""))
  • ouput
true
false
true
true
  1. Index查找位置
func Index(s, sep string) int
  • 子串sep在字符串s中第一次出现的位置,不存在则返回-1。
  • exmaple
fmt.Println(strings.Index("chicken", "ken"))
fmt.Println(strings.Index("chicken", "dmr"))
  • output
4
-1
ToLower, ToUpper
  1. ToLower字母小写
func ToLower(s string) string
  • 返回将所有字母都转为对应的小写版本的拷贝。
  • exmaple
fmt.Println(strings.ToLower("Gopher"))
  • output
gopher
  1. ToUpper字母大写
func ToUpper(s string) string
  • 返回将所有字母都转为对应的大写版本的拷贝

  • exmaple

fmt.Println(strings.ToUpper("Gopher"))
  • output
GOPHER
Trim,TrimRight,TrimLeft
  1. Trim
func Trim(s string, cutset string) string
  • 返回将s前后端所有cutset包含的utf-8码值都去掉的字符串。

  • exmaple

fmt.Printf("[%q]", strings.Trim(" !!! Achtung! Achtung! !!! ", "! "))
  • output
["Achtung! Achtung"]
  1. TrimLeft
func TrimLeft(s string, cutset string) string
  • 返回将s前端所有cutset包含的utf-8码值都去掉的字符串。
  1. TrimRight
func TrimRight(s string, cutset string) string
  • 返回将s后端所有cutset包含的utf-8码值都去掉的字符串。

Go内建容器——Golang学习笔记3相关推荐

  1. golang学习笔记之--Go语言内建容器

    话接上文 <golang学习笔记之--Go语言基本语法> 今天继续记录学习笔记,今天的笔记主题是Go语言内建容器 如果各位童鞋想要获得下面的源码,请搜索gzh:隔壁王小猿,关注后回复&qu ...

  2. golang学习笔记(基础篇)

    LCY~~Golang学习笔记 一.Go语言开发环境 ##安装Go开发包以及VsCode Go开发包与vscode配置安装教程网址:https://www.liwenzhou.com/posts/Go ...

  3. 118云原生编程语言Golang学习笔记

    Golang学习笔记 文章目录 1.Go简介 1.1 简介 1.2 设计初衷 1.3 Golang vs Java 1.4 应用领域 1.5 用go语言的公司 2.Go下载和安装 2.1 开发工具 2 ...

  4. golang学习笔记(五):数组的定义和使用

    golang 学习笔记 数组定义 数组是一系列相同数据类型在内存中有序存储的数据集合 var 数组名 [元素个数]数据类型//定义了10个整型变量的数组元素var arr [10]int//通过下标找 ...

  5. Golang学习笔记之GORM基础使用(二)

    本文章主要学习GORM的增删查改.若还没有完成数据库和数据表的创建.定义模型以及数据库的连接请先学习本本专栏文章Golang学习笔记之GORM基础使用(一).本文为学习笔记,通过GORM官方中文文档和 ...

  6. golang学习笔记8 beego参数配置 打包linux命令

    golang学习笔记8 beego参数配置 打包linux命令 参数配置 - beego: 简约 & 强大并存的 Go 应用框架 https://beego.me/docs/mvc/contr ...

  7. golang学习笔记12 beego table name `xxx` repeat register, must be unique 错误问题

    golang学习笔记12 beego table name `xxx` repeat register, must be unique 错误问题 今天测试了重新建一个项目生成新的表,然后复制到旧的项目 ...

  8. golang学习笔记(十六):多态的实现

    golang 学习笔记 多态实现 package main import "fmt"//先定义接口 在根据接口实现功能 type Humaner1 interface {//方法 ...

  9. golang学习笔记-1

    golang学习笔记-1 自学golang时,找到一篇学习资料http://golang.iswbm.com/en/latest/c01/c01_08.html 初看上面两种写法,不明就里,哪里高级了 ...

最新文章

  1. SMO学习笔记(二)——还原(恢复)篇之完整恢复
  2. centos7配置br0_centos 7.2 网卡配置文件 及 linux bridge的静态配置
  3. python自学教程 pdf-《Python编程从入门到精通》PDF高清完整版-PDF下载
  4. Today's my MDX...
  5. Physical Standby Databases Role Transfer
  6. matlab绘图基础,matlab绘图基础
  7. windows xp共享访问提示“拒绝访问”的故障处理步骤
  8. 1093-A+B for Input-Output Practice (V)
  9. 远方的人 -- 龙瑜
  10. 得到APP之订阅专栏《硅谷来信》和《精英日课》目录
  11. 50种让你的网站被关注的方法
  12. 7-13 寻找大富翁 (25分)
  13. 陕南柿子红了_陕南赤子_新浪博客
  14. 基层管理者的第一步——从“我”变成“我们”
  15. c++中如何把任意类型的指针转化为void*
  16. L298N驱动俩路电机按键控制正反转
  17. 常见网络摄像机(摄像头)的端口及RTSP地址
  18. 统计图配色方案_填充
  19. android 监听短信并获取验证码
  20. 极光开发者周刊【No.0730】

热门文章

  1. 虚拟偶像,人类探索元宇宙的萌芽
  2. 【ZBrush雕刻】3D机械模型!LOL英雄联盟“烬”教程分享
  3. Android应用卸载器
  4. ArGIS Engine专题(2)之地图同步
  5. 当医药保健遇见“互联网+”和数据,就可以赢得整个江湖
  6. 什么东西可以改善睡眠,这些助眠好物让你远离失眠
  7. python-读取excel文件
  8. arcgis engine 将图层要素复制到另一个图层
  9. 提升开发效率N倍的20+命令行神器!(附 demo)
  10. 【HDU No. 1166】 敌兵布阵