Go基础
相比于其他语言的好处?
- 做了并发优化,支持kmp模型
- 语言具有可读性
- 垃圾回收效率更高
什么是协程?
切片和数组
切片:动态扩缩容,指针传递
数组:固定容量,值传递
1 | func modify(arr [3]int) { |
make初始化会把长度的元素都站住,初始化值为0,这个时候append会扩容,因为初始化的len和cap相等
len当前长度;cap容量;
1 | s := make([]int, 5) |
一般切片初始化写法:
1 | make([]int, 5) → [0 0 0 0 0] len=5 cap=5 |
使用for range 的时候,它的地址会发生变化吗?
1.22之前地址不会变,每次都是同一个变量,共享同一个空间,
1.22之后,每一个迭代内容都是新变量,
1 | for index, value := range collection {// ...} |
这里 value 是一个副本。在每次迭代中,collection 中的当前元素值会被复制到 value 这个变量中。Go 编译器通常会为 value 分配一块固定的内存地址,然后在每次迭代时,将当前元素的值覆盖到这块内存中。所以,当你打印 &value 时,你会发现它的内存地址在整个循环过程中都是保持不变的。
**优化点:**牺牲少量内存换取代码的安全性
1 | // go1.21 及之前 |
闭包是指函数直接修改外部的变量
defer关键字
不论包含 defer 语句的函数是通过 return 正常结束,还是由于 panic 导致的异常结束,defer在注册成功的前提下都会执行。
你可以在一个函数中执行多条 defer 语句,它们的执行顺序与声明顺序相反。自下而上传递
1 | func main() { |
空struct{}作用
struct{}占用空间为0
- 可以在map中当作value去模拟set
1 | type Set map[string]struct{}func main() { |
- channel传递信号
1 | done := make(chan struct{}) |
1 | ch <- struct{}{} |
init执行顺序
执行顺序:import –> const –> var –>init()–>main()
interface{}是什么
它是空接口——可以理解为”任意类型”,any是interface的别名
1 | interface{} = { type, value } |
1 | var x interface{} |
1 | func describe(v interface{}) { |
Go语言中”_“的作用
- 忽略返回值
- 忽略包内容,但是执行init
go内存泄漏
- Go goroutine泄漏
携程无法退出,内部的引用变量全部无法释放
- **场景:**无缓冲channel读/写,对方不发消息,阻塞在条件变量一直等不到信号
- 示例:
ch := make(chan int); go(func(){<-ch})(),没人往 ch 发数据,协程永久挂起。 ✨排查:pprof goroutine查看大量阻塞协程栈
- 无用对象无法释放
- HTTP 请求不关闭 resp.Body
resp.Body没有defer resp.Body.Close(),底层连接和 buffer 无法回收,连接池堆积、内存上涨。