0%

go中字符串,切片,数组,map

数组Array

  • 是同一种数据类型的固定长度的序列。

  • 数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值

  • 数组定义:var a [len]T,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义,长度不能变。

  • 初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
全局:
var arr0 [5]int = [5]int{1, 2, 3}
var arr1 = [5]int{1, 2, 3, 4, 5}
var arr2 = [...]int{1, 2, 3, 4, 5, 6}
var str = [5]string{3: "hello world", 4: "tom"}
局部:
a := [3]int{1, 2} // 未初始化元素值为 0。
b := [...]int{1, 2, 3, 4} // 通过初始化值确定数组长度。
c := [5]int{2: 100, 4: 200} // 使用索引号初始化元素。
d := [...]struct {
name string
age uint8
}{
{"user1", 10}, // 可省略元素类型。
{"user2", 20}, // 别忘了最后一行的逗号。
}

字符串

如下代码所示:

  • 函数外定义字符串,为全局变量
  • 在函数内定义s3 := “5555”,为局部变量
  • 循环字符串时,单个字符的类型为byte,而字符有两种类型
    • 一种是 uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符
    • 另一种是 rune 类型,代表一个 UTF-8 字符,如中文,rune 类型等价于 int32 类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 全局定义字符串
var s1 = `
111
222
33
`
var s2 = "4444"

func main() {
// 局部定义
s3 := "5555"
var a = "中"
fmt.Println(s1, s2, s3, a)
s := "pprof.cn博客"
for i := 0; i < len(s); i++ { //byte
fmt.Printf("%v(%c) ", s[i], s[i])
//112(p) 112(p) 114(r) 111(o) 102(f) 46(.) 99(c) 110(n) 229(å) 141() 154() 229(å) 174(®) 162(¢)
}
fmt.Println()
// 打印中文,需转换为rune类型
for _, r := range s { //rune
fmt.Printf("%v(%c) ", r, r)
//112(p) 112(p) 114(r) 111(o) 102(f) 46(.) 99(c) 110(n) 21338(博) 23458(客)
}
fmt.Println()

s1 := "hello"
// 强制类型转换
byteS1 := []byte(s1)
byteS1[0] = 'H'
fmt.Println(reflect.TypeOf(byteS1[0])) // uint8
fmt.Println(string(byteS1)) //Hello

s2 := "博客"
runeS2 := []rune(s2)
runeS2[0] = '狗'
fmt.Println(string(runeS2)) //狗客

byte

  • 在字符串中代码已经详细说明了byte的定义,就是字符串中的每一个元素叫做“字符”,在遍历或者单个获取字符串元素时可以获得字符。

切片Slice

初始化

  • 看如下代码,为声明和初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//1.声明切片,int类型的数组
var s1 []int
if s1 == nil {
fmt.Println("是空")
} else {
fmt.Println("不是空")
}
// 2.:=
s2 := []int{}
// 3.make()
var s3 []int = make([]int, 0)
fmt.Println("s1,s2,s3", s1, s2, s3) // s1,s2,s3 [] [] []
// 4.初始化赋值
var s4 []int = make([]int, 0, 0)
fmt.Println("s4=", s4) // s4= []
s5 := []int{1, 2, 3}
fmt.Println(s5)
// 5.从数组切片
arr := [5]int{1, 2, 3, 4, 5}
var s6 []int
// 前包后不包
s6 = arr[1:4]
fmt.Println("s6=", s6) //s6= [2 3 4]

append

  • 切片追加
1
2
3
4
5
6
7
8
9
10
11
var a = []int{1, 2, 3}
fmt.Printf("slice a : %v\n", a) // slice a : [1 2 3]
var b = []int{4, 5, 6}
fmt.Printf("slice b : %v\n", b) // slice b : [4 5 6]
c := append(a, b...)
fmt.Printf("slice c : %v\n", c) //slice c : [1 2 3 4 5 6]
d := append(c, 7)
fmt.Printf("slice d : %v\n", d) // slice d : [1 2 3 4 5 6 7]
e := append(d, 8, 9, 10)
fmt.Printf("slice e : %v\n", e) // slice e : [1 2 3 4 5 6 7 8 9 10]

  • 向 slice 尾部添加数据,返回新的 slice 对象
1
2
3
4
5
6
7
s1 := make([]int, 0, 5)
fmt.Printf("%p\n", &s1) // 0xc000008078

s2 := append(s1, 1)
fmt.Printf("%p\n", &s2) // 0xc000008090

fmt.Println(s1, s2) // [] [1]

总结

  • 切片是指针类型,数组是值类型
  • 数组的赋值形式为值传递,切片的赋值形式为引用传递
  • 数组的长度是固定的,而切片长度可以任意调整(切片是动态的数组)
  • 数组只有长度一个属性,而切片比数组多了一个容量(cap)属性

map

  • map是一种无序的基于key-value的数据结构
  • 定义 map[KeyType]ValueType,如map[string]int
1
2
3
4
5
6
7
8
9
10
11
func main(){
// 使用make初始化一个map
scoreMap := make(map[string]int)
scoreMap["张三"] = 90
scoreMap["小明"] = 100
scoreMap["王五"] = 60
delete(scoreMap, "小明")//将小明:100从map中删除
for k,v := range scoreMap{
fmt.Println(k, v)
}
}

元素为map类型的切片

  • 对应于python中的[{"name":"王五","password": "123456", "address":"红旗大街"},{}]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var mapSlice = make([]map[string]string, 3)
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value) //index:0 value:map[]
}
fmt.Println("after init")
// 对切片中的map元素进行初始化
mapSlice[0] = make(map[string]string, 10)
mapSlice[0]["name"] = "王五"
mapSlice[0]["password"] = "123456"
mapSlice[0]["address"] = "红旗大街"
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
// index:0 value:map[address:红旗大街 name:王五 password:123456]
//index:1 value:map[]
for k, v := range value {
fmt.Println("k=", k, "v=", v)
//k= name v= 王五
//k= address v= 红旗大
}
}
fmt.Println(mapSlice) // [map[address:红旗大街 name:王五 password:123456] map[] map[]]

值为切片类型的map

  • 对应于python中{“中国”:[“北京”, “上海”]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var sliceMap = make(map[string][]string, 3)
fmt.Println(sliceMap)
fmt.Println("after init")
key := "中国"
value, ok := sliceMap[key]
if !ok {
value = make([]string, 0, 2)
}
value = append(value, "北京", "上海")
sliceMap[key] = value
fmt.Println(sliceMap) //map[中国:[北京 上海]]
fmt.Println(sliceMap["中国"]) // [北京 上海]
for _, v := range sliceMap["中国"] {
fmt.Println(v)
// 北京
// 上海
}
fmt.Println(sliceMap) //map[中国:[北京 上海]]

interface

  • interface是一种抽象的类型,可以用来表示任何类型

  • 比如如下场景,不像写结构体,就可以用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
js := `{"int":1,"string":"qwertyuiop","float":1.111}`
jsm := make(map[string]interface{})
// 反序列化
err := json.Unmarshal([]byte(js), &jsm)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(jsm) // map[float:1.111 int:1 string:qwertyuiop]
for k, v := range jsm {
fmt.Println("k=", k, "v=", v)
}


类型转换

byte 转换为string

  • data1.json中内容为:
1
2
3
1 2
2 3
中国 4
  • 代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
f, err := os.Open("hello_work\\data1.json")
if err != nil {
fmt.Println("open file eror:", err)
return
}
defer f.Close()
// 读取文件内容,类型为[]byte
byteValue, _ := ioutil.ReadAll(f)
fmt.Println(byteValue) // [49 32 50 13 10 50 32 51 13 10 228 184 173 229 155 189 32 52]
fmt.Println(reflect.TypeOf(byteValue)) // []uint8
s := string(byteValue)
for _, v := range s {
fmt.Println(string(v))
}

string 转换为map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package conver

import (
"encoding/json"
"fmt"
"reflect"
)

type User struct {
Code int
Msg string
}

func StrT() {
js := `{"code":1,"msg":"qwertyuiop"}`
// 定义一个map的key为string,值类型为不确定的结构体
jsm := make(map[string]interface{})
// 反序列化
err := json.Unmarshal([]byte(js), &jsm)

if err != nil {
fmt.Println(err)
return
}
fmt.Println(jsm) // map[code:1 msg:qwertyuiop]

var user User
err1 := json.Unmarshal([]byte(js), &user)
if err1 != nil {
fmt.Println(err1)
return
}
fmt.Println(user) //{1 qwertyuiop}
fmt.Println(reflect.TypeOf(user)) //conver.User
}

byte 转换为map

  • data.json内容
1
{"code": 1, "msg":"success", "data":[{"id": 1, "name":"西瓜"},{"id": 2, "name": "苹果"}]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
f, err := os.Open("hello_work\\data.json")
if err != nil {
fmt.Println("open file eror:", err)
return
}
defer f.Close()
byteValue, _ := ioutil.ReadAll(f)

// 定义一个map的key为string,值类型为不确定的结构体
jsm := make(map[string]interface{})
// 反序列化
err1 := json.Unmarshal(byteValue, &jsm)

if err1 != nil {
fmt.Println(err)
return
}
fmt.Println(jsm) // map[code:1 data:[map[id:1 name:西瓜] map[id:2 name:苹果]] msg:success]

// map转换为string
dataType, _ := json.Marshal(jsm)
dataString := string(dataType)
fmt.Println(dataString)

map转换为string

  • 在byte 转换为map中,最后三行代码就是把map转为string
1
2
3
dataType, _ := json.Marshal(jsm)
dataString := string(dataType)
fmt.Println(dataString)

其他