数据类型
字符串
字符串是不可变字节序列
字符串默认值" ",不是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]\n", i, s[i])
}
for i, c := range s { //返回数组索引号,以及unicode字符
fmt.Printf("%d [%c]\n", 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\t", 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
}

浙公网安备 33010602011771号