这是我参与「第五届青训营 」笔记创作活动的2天
6.数据结构
(1)数组
这里的数组和c中的数组一样,长度固定
fmt.Println("Array")
var array [3]int
array[1] = 2
fmt.Println(array, len(array)) //[0 2 0] 3
array_1 := [3]int{1, 2, 3}
fmt.Println(array_1) //[1 2 3]
Two_array := [2][3]int{{1, 2, 3}, {4, 5, 6}}
fmt.Println(Two_array) //[[1 2 3] [4 5 6]]
- 这里的定义方式很多,很灵活,但需要初始化数组长度
- 二维数组的定义方式也很简洁
- 这里介绍一个函数,len(),返回数组长度,在后面的切片,map等都可使用
(2)切片
这里的切片很想python的列表,长度不固定
fmt.Println("List")
list := make([]string, 3)
list[0] = "apple"
list[1] = "banana"
list[2] = "orange"
fmt.Println("list:", list) //list: [apple banana orange]
fmt.Println("list_len:", len(list)) //list_len: 3
list = append(list, "watermelon")
fmt.Println("list_len:", len(list)) //list_len: 4
list_2 := make([]string, 5)
copy(list_2, list)
fmt.Println("list_2:", list_2) //list_2: [apple banana orange watermelon ]
fmt.Println("list_2_len:", len(list_2)) //list_2_len: 5
- 可以使用make定义变量,按下标赋值和输出
- 初始时可以给定长度也可以不给长度
- copy(a,b),拷贝切片,这个是浅拷贝和是深度拷贝暂时不知道,待后面探讨清楚
- append()添加元素,这个和python很想
(3)Map(字典)
//map, [kry]value,traversal disorder
fmt.Println("Map")
good := make(map[string]int)
good["apple"] = 3
good["orange"] = 6
fmt.Println(good) //map[apple:3 orange:6]
fmt.Println(len(good)) //2
fmt.Println(good["apple"]) //3
fmt.Println(good["watermelon"]) //0
//r = good["banana"] , ok = Whether there is [True or False]
r, ok := good["banana"]
fmt.Println(r, ok) //0 false
//delete Key-pair value
delete(good, "orange")
fmt.Println(good) //map[apple:3]
//Other ways to assign values
m := map[string]int{"apple": 3, "banana": 2}
fmt.Println(m) //map[apple:3 banana:2]
var m2 = map[int]string{3: "apple", 2: "banana"}
fmt.Println(m2) //map[2:banana 3:apple]
- 这里的Map类似c,java,python这些的字典,以键对值的形式存储
- 定义形式也是有很多
- 这里有一个新知识,就是如果输出没有的键对值不会报错,int型返回0,这里提供了一个方法,r,ok := map[key],如果key不存在,r返回默认值,ok返回boolean
(4)range方法
nums := []int{1, 2, 3}
for i, v := range nums {
fmt.Println(i, v)
}
maps := map[string]int{"a": 1, "b": 2}
for k, v := range maps {
fmt.Println(k, v)
}
- range遍历键对值,可以遍历Map
- 也可以遍历元组和切片,index:value,和python的enumerate功能一样
(5)结构体
//定义结构体
type user struct {
name string
password string
}
func main(){
a := user{name: "mao", password: "123456"}
b := user{"mao", "12345"}
var c user
c.name = "mao"
c.password = "1234"
fmt.Println(a, b, c)
}
- 和c语言的结构体类似
- 作为参数时加指针才可修改结构体内容
7.函数
func add(a, b int) int {
return a + b
}
func exists(m map[string]string, k string) (string, bool) {
v, ok := m[k]
return v, ok
}
func main() {
res := add(3, 4)
fmt.Println(res) //7
v, ok := exists(map[string]string{"A": "a", "B": "b"}, "A")
fmt.Println(v, ok) //a False
}
- 和其它语言大同小异,规规矩矩
8.指针
func add2(n *int) {
*n += 2
}
func mian(){
n := 2
add2(&n)
fmt.Println(n) //4
}
- go的指针操作有限,不想c和c++那样,go多用于修改函数参数
- 普通函数传参方式为拷贝,如果想要直接修改参数需要开辟新的内存,这样对于体量较大的数据来说不太友好
- 当时学c的时候就苦恼于指针,不过好在go的指针并没有那么复杂
- 相对这一块来说我更倾向于python的可变参数与不可变参数
9.结构体方法
type user struct {
name string
password string
}
func (u user) checkPasswd(password string) bool {
return u.password == password
}
func main(){
a := user{name: "mao", password: "123456"}
fmt.Println(a.checkPasswd("123456"))
}
- 故名思意就是在结构体内部定义一个函数变量
- 可以比作python中的类方法
- 这里如果想要修改结构体中的变量内容仍然需要使用指针
10.错误处理
type user struct {
name string
password string
}
func (u user) findPasswd() (pawd string, err error) {
if u.password != "" {
return u.password, nil
} else {
return "", errors.New("no found")
}
}
func main(){
a := user{name: "mao", password: "123456"}
if p, err := a.findPasswd(); err != nil {
fmt.Println(err)
} else {
fmt.Println(p)
}
}
- 使用错误处理需要导入一个errors包
- 额,这里会用是会用了,但属实有点不太理解有什么用,感觉就是定义了一个错误变量,有点像是主动抛出异常吧,好像多是用于函数,具体用途后面应该会知道
11.字符串格式化
type user struct {
name string
password string
}
func main(){
a := user{name: "mao", password: "123456"}
fmt.Printf("a=%v\n", a) //a={mao 123456}
fmt.Printf("a=%+v\n", a) //a={name:mao password:123456}
fmt.Printf("a=%#v\n", a) //a=main.user{name:"mao", password:"123456"}
pi := 3.1415926
fmt.Printf("pi=%.2f", pi) //pi=3.14
}
- 这个字符串格式化我很喜欢,他有%v,这样可以不去判断类型直接输出
- 并且有+v,#v这些,省区了一些其它步骤
- 而且也有%.2f这样的格式化
- 但我更喜欢python3的f'{}',更加方便直观和灵活,只是没有+v,#v这些🥲🥲🥲
12.json处理
type people struct {
Name string
Age int `json:"age"`
Sex string
}
func main() {
my := people{
Name: "Mao xiaocheng",
Age: 21,
Sex: "male",
}
buf, err := json.Marshal(my)
if err != nil {
panic(err)
} else {
fmt.Println(string(buf)) //{"Name":"Mao xiaocheng","age":21,"Sex":"male"}
}
var buf2 map[string]any
err = json.Unmarshal(buf, &buf2)
if err != nil {
panic(err)
}
fmt.Println(buf2) //map[Name:Mao xiaocheng Sex:male age:21]
}
- 使用前需要导入encoding/json包
json.Marshal转化为json数据,需要注意这里的返回,有一个err,用来返回错误json.Unmarshal解析json对象,同样注意返回,并且第二个参数需要加&,使用指针直接修改参数- 还有很多json方法,待以后慢慢学习
- 需要注意的是要想转化为json键值首字母为大写,如上,如果想要小写在后面加
json:"age",设计原理暂不知晓 - 还有如果要输出json则需要转化为string,否则输出进制数据
今日总结:
感觉学的东西太多,一下消化不了而且很多东西没有细究,加起来一共半天时间就过完了感觉很多东西没有细究,虽然是理解了但一些原理什么的没有搞清楚,之后得好好再学一次,不然很难受。不愧是字节,太卷了。。。但我不想内卷,那是精神内耗,做自己就行😉😉😉
瑞思拜😭😭😭