字符串
字符串是不可变字节序列
字符串默认值" ",不是nil
使用"`"定义不做转义的原始字符串,支持跨行
支持"!=,<,>,=="操作符
package main import ( "fmt" ) func main() { s := "ab" + "cd" fmt.Println(s == "abcd") fmt.Println(s > "abc") }
允许索引号访问字节数组,但是不能获取元素地址
for遍历字符串时,分byte rune两种方式
package main import ( "fmt" ) func main() { s := "想飞上天" for i := 0; i < len(s); i++ { // byte fmt.Printf("%d [%c] ", i, s[i]) } for i, c := range s { //返回数组索引号,以及unicode字符 fmt.Printf("%d [%c] ", i, c) } }
rune
func main() { s := "yes我爱慕课网!" for _, ch := range []rune(s) { fmt.Printf("%c", ch) }
字符串拼接
加法操作拼接字符串时,每次都需要重新分配内存
改进:预分配足够的内存空间
package main import ( "fmt" "strings" ) func test() string { s := make([]string, 1000) //分配足够的内存 for i := 0; i < 1000; i++ { s[i] = "a" } return strings.Join(s, "") } func main() { result := test() fmt.Println(result) }
数组
定义数组类型时,长度是类型组成部分,元素类型相同,但长度不同的数组不属于同一类型
数组的初始化方式
package main import ( "fmt" ) func main() { var a [4]int //元素自动初始化为零 b := [4]int{2, 5} //未提供初始化的元素自动初始化为0 c := [4]int{5, 3: 10} //指定索引位置初始化 d := [...]int{1, 2, 3} // 编辑器按初始化值数量确定数组长度 e := [...]int{10, 3: 100} // 支持索引初始化,但注意数组长度与此有关 fmt.Println(a) fmt.Println(b) fmt.Println(c) fmt.Println(d) fmt.Println(e) }
- [10] int和[20] int 是不同的数据类型
- 使用var定义时不需要初始化值,:= 需要写上初始值
- 数组是值类型,作为参数传入函数中,不会改变初始值;想要改变可以用指针a *[5] int
通过指针修改数组
func array(a *[5]int) { a[0] = 100 for _, v := range a { fmt.Println(v) } } func main() { var a [5]int array(&a) }
对于结构复杂的类型,省略元素初始化类型标签
package main import ( "fmt" ) func main() { type user struct { name string age int } d := [...]user{ {"tom", 20}, {"jack", 22}, } fmt.Println(d) }
在定义多维数组时,仅第一维度允许使用"..."
package main import ( "fmt" ) func main() { a := [2][2]int{ {1, 2}, {3, 4}, } b := [...][2]int{ {1, 2}, {3, 4}, {5, 6}, } fmt.Println(a) fmt.Println(b) }
切片
切片的几种创建方式
s6 := []int{1, 2, 3} //不指定长度 s7 := make([]int, 10) //指定长度10 s8 := make([]int, 10, 30) //长度10,cap30
切片取值
func array(a [7]int) { s := a[2:6] fmt.Println(s) } func main() { array([...]int{1, 2, 3, 4, 5, 6, 7}) }
左开右闭,输出结果
[3 4 5 6]
切片copy,delete
func main() { s1 := make([]int, 10, 30) //长度10,cap30 s2 := []int{2, 4, 6, 8} //copy slice copy(s1, s2) fmt.Println(s1) //delete slice s3 := append(s1[:3], s1[4:]...) fmt.Println(s3) }
输出结果
[2 4 6 8 0 0 0 0 0 0] [2 4 6 0 0 0 0 0 0]
引用传递,修改数组值
func printArray(a []int) { a[0] += 100 } func main() { array := [...]int{0, 1, 2, 3, 4, 5, 6, 7} printArray(array[:]) //数组转切片 [:] fmt.Println(array) }
输出
[100 1 2 3 4 5 6 7]
反转数组a
package main import "fmt" func reverse(s []int) { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } } func main() { a := [...]int{0, 1, 2, 3, 4, 5} reverse(a[:]) fmt.Println(a) }
slice扩展
func main() { array := [...]int{0, 1, 2, 3, 4, 5, 6, 7} s1 := array[2:6] s2 := s1[3:5] fmt.Println(s1, s2) //slice可以向后扩展,不能向前扩展 //len切片长度 cap切片容量
//s[i]不可以超越len(s),向后扩展不可以超越底层数组cap(s) }
输出
[2 3 4 5] [5 6]
添加元素时如果超越cap,系统会重新分配更大的底层数组
func main() { array := [...]int{0, 1, 2, 3, 4, 5, 6, 7} s1 := array[2:6] s2 := s1[3:5] s3 := append(s2, 10) s4 := append(s3, 11) s5 := append(s4, 12) fmt.Println(s3, s4, s5, array) }
输出
[5 6 10] [5 6 10 11] [5 6 10 11 12] [0 1 2 3 4 5 6 10]
指针
指针数组是指元素为指针类型的数组,数组指针是获取数组变量的地址
数组指针可直接用来操作元素
package main import ( "fmt" ) func main() { x, y := 10, 20 a := [...]int{x, y} p := &a p[1] += 10 fmt.Println(p[1]) fmt.Println(p) }
复制
数组是值类型,赋值和传参都会copy数据,可改用指针或切片避免
字典
字典是引用类型,make函数创建
创建
package main import ( "fmt" ) func main() { m := make(map[string]int) m["a"] = 1 m["b"] = 2 m2 := map[int]struct{ x int }{ //值为匿名结构类型 1: {x: 100}, 2: {x: 200}, } fmt.Println(m) fmt.Println(m2) }
package main import ( "fmt" "sort" ) func testMap() { // var a map[string]string = map[string]string{"abc": "edf"} a := make(map[string]string, 10) a["abc"] = "edf" fmt.Println(a) } func testMap2() { a := make(map[string]map[string]string, 10) a["key"] = make(map[string]string, 10) a["key"]["key1"] = "1" a["key"]["key2"] = "2" fmt.Println(a) } func testMapSort() { a := make(map[int]int, 5) a[8] = 10 a[1] = 10 a[4] = 10 a[5] = 10 a[2] = 10 var keys []int for k, _ := range a { keys = append(keys, k) } sort.Ints(keys) for _, v := range keys { fmt.Println(v, a[v]) } } func main() { // testMap2() testMapSort() }
基本操作
package main import ( "fmt" ) func main() { m := map[string]int{ "a": 1, "b": 2, } m["a"] = 10 //修改 m["c"] = 30 //新增 if v, ok := m["d"]; ok { //判断key是否存在,不存在默认返回零值 println(v) } delete(m, "c") //删除 fmt.Println(m) }
对字典进行迭代,每次返回的键值次序不相同
package main import ( "fmt" ) func main() { m := make(map[string]int) for i := 0; i < 10; i++ { m[string('a'+i)] = i } for i := 0; i < 4; i++ { for k, v := range m { fmt.Printf("%v:%v ", k, v) } fmt.Println() } }
因内存访问安全和哈希算法等缘故,字典被设计成not addressable,不能直接修改value成员(结构体或数组)
package main type user struct { name string age int } func main() { m := map[int]user{ 1: {"alex", 20}, } m[1].age += 1 //error }
正确做法是先返回整个value,修改后重设字典键值 或者通过指针
package main import ( "fmt" ) type user struct { name string age int } func main() { m := map[int]user{ 1: {"alex", 20}, } m2 := map[int]*user{ 1: &user{"jack", 25}, } u := m[1] u.age = 18 m[1] = u m2[1].age++ //m2[1]返回的是指针,可透过指针修改目标对象 fmt.Println(m) fmt.Println(*m2[1]) }
寻找最长不含有重复字符的子串
思路:对于每一个字母x,lastoccured[x]不存在,或者<start ;无需操作
lastoccured[x]>= start ;更新start
更新lastoccured[x],更新maxlength
func lengthOfLongestSubstring(s string) int { lastOccured := make(map[byte]int) start := 0 maxLength := 0 for i, ch := range []byte(s) { if lastI, ok := lastOccured[ch]; ok && lastI >= start { start = lastI + 1 } if i-start+1 > maxLength { maxLength = i - start + 1 } lastOccured[ch] = i } return maxLength }