数据结构与 方法(增删改查)
-
安装goland,注意版本是2024.1.1,不是2024.2.1,软件下载地址也在链接中提供了
-
‘go’ 不是内部或外部命令,也不是可运行的程序
或批处理文件。
在 Windows 搜索栏中输入“环境变量”,然后选择“编辑系统环境变量”或“编辑环境变量”。
在系统属性窗口中,点击“环境变量”按钮。
在“系统变量”区域,找到并选择“Path”变量,然后点击“编辑”。
在弹出的窗口中,点击“新建”,然后输入 Go 的 bin 目录的路径,例如 C:\Go\bin。
点击“确定”保存更改。
-
枚举用 iota自动就依次排号变成枚举了,不用你赋值了。枚举就是变量代替正整数
有类型的枚举的话,就不能 float64+ int了,因为有严格的类型校验,没指明类型的可以 -
字符串拼接可以用 +
数据不可变,它的值改变不了
字符串不可变: 意味着你不能改变字符串内部的单个字符。
变量可变: 变量本身可以被重新赋值,指向另一个字符串。
var newName string
newName = name + " " + "day"
fmt.Println(newName)
newName += "s"
fmt.Println(newName)
从行为上看,newName 的内容变了,但这是因为你指向了一个全新的字符串。在 Go 中,这种操作不是修改原有字符串,而是创建了一个新的字符串,并让 newName 指向这个新的字符串。原有的字符串 “lucky day” 仍然存在于内存中,直到 Go 的垃圾收集器决定回收它。
- 结构体就是复合类型的聚合
指针,如果p = &s(结构体) ,通过取地址运算符取到指针, 那么p就能像 s一样点出来所有内含的字段 - 数组
长度固定,存储同一类型的数据。数组是值传递的,不是引用传递,每次作为参数都是值传递,数组太大,复制会引起性能损耗。解决方案就是使用切片
切片 【指针,len, cap容量 cap>=len】
可以动态改变长度(每次大于容量再append元素,容量是翻倍的涨,比如1,2,4,8),一旦扩容,切片就会和原数组解绑,然后绑定到一个新数组上。频繁扩容耗费性能。所以初始化的时候,len可以设置为0,但是容量最好设置一个预估的值
len就是切片里元素的个数,
切片是对底层数组的描述的意思是当改动切片中的某个值,从切片用中括号截取的切片对应的值也会改变,它从根上就变化了。
容量cap就是你把原切片切出一部分,容量就是原容量减去中括号前面切去的就是现在的容量
- golang是编译语言,python是脚本语言
脚本语言:适用于快速开发、自动化任务、Web开发和应用程序扩展。它们的价值在于提高开发效率和灵活性。
编译语言:适用于高性能应用、系统编程、大型企业应用和安全性要求高的场景。它们的价值在于提供高效的执行速度和对底层系统的控制。
-
make 只能用于内置的切片、映射和通道类型,不能用于用户定义的类型或其他内置类型(如整型、浮点型等)。对于这些类型,你需要使用其他方式(如直接初始化或使用 new 函数)来创建和初始化变量。
-
map 哈希表或者字典,k-v。
遍历map的时候是无序的。map也是有容量的,如果频繁扩容也会造成性能消耗 -
切片(slice)、映射(map)和通道(channel)是引用类型,其他的是值类型
-
这里num的作用域就是if 函数内。err经常用这一招
-
for循环重复执行一段代码,直到不满足条件为止
for range用来遍历 切片 map 数组,string 等用的,下面是range和传统形式两种
[]string{“lucky”,“nike”,“allen”}中括号里没东西就是切片,有数值就是数组
-
包就是import那个,
package中 首字母大写的函数是可以被导出的,首字母小写的就是内部使用的
构建就是 go build xx.go,xx.go就是你的那个package xx脚本。然后就可以在命令行直接执行 ./xx 跟 go run xx.go一样的效果
如果有两个errors包(不需要go build的,脚本形式就行),只需要前面加上来源,比如github.com/pkg/errors,并且给它取个别名来解决包冲突
包名一般跟顶层文件夹名保持一致
交叉编译(Cross-Compilation)是指在一种平台上编译生成能够在另一种平台上运行的程序。也就是说,编译代码的机器和运行该代码的目标机器使用不同的操作系统或硬件架构。交叉编译通常用于开发需要在多个平台(如 Linux、Windows、macOS,或不同的处理器架构如 ARM、x86)上运行的程序。
Go 语言内置了对交叉编译的强大支持。Go 的编译器允许开发者通过设置两个环境变量GOOS
(目标操作系统)和GOARCH
(目标硬件架构)来进行交叉编译。
例如,想要在 Linux 上编译一个能在 Windows 运行的程序,开发者可以这样做:
GOOS=windows GOARCH=amd64 go build -o myapp.exe
同理,想要编译一个能在 ARM 架构的 Linux 设备上运行的 Go 程序,可以设置:
GOOS=linux GOARCH=arm64 go build -o myapp
-
函数
func init(){}
func 函数名(参数)(返回值){
函数体
defer 函数:当前函数结束时候调用 //主要用于释放资源。因为中间函数发生错误,return掉了,这时就没法执行关闭资源的代码,这时候defer就能派上用场了。比如ioutil.ReadAll(file)的时候,需要 file.Close()
} -
方法
相较于函数,多了一个 接收者 receiver,用来连接方法与类型,比如结构体的方法,不能是基础类型,int,string这些
receiver参数可以是值类型(用于只读),也可以是指针类型(读写)。
-
接口,里面有没有实现的方法。我开放了我的系统,但你实现要符合我的规则,也就是接口
接口组合就是 接口套接口或者 结构体里面套接口 -
并发与并行
同时运行多个任务,交替进行,不一定在同一时刻都在运行的是并发。 都在同一时刻运行的是并行。并行需要多核cpu或者分布式计算系统
并行那么棒,为啥需要并发
1)并发可以让 I/O 操作等待的时间里去做其他事情(其他协程或者线程切进来工作)。比如在等朋友的时候,你还可以玩玩手机,不是干等。
2)防止死锁
协程
用了协程,干一件事用10ms,干5件事也是10ms
创建协程,使用WaitGroup 等待协程结束(防止协程还没执行,main函数先执行完了,就都结束了)
解决并发同时访问一个资源不安全的问题,用mutex.Lock() 互斥锁。访问的时候变成了串行。锁的位置要放准,锁太多执行效率会下降