GO笔记

为什么有延迟语句
  • 编程的时候,经常需要申请一些资源,比如数据库连接、文件、锁等,这些资源需要在用完之 后释放掉,否则会造成内存泄漏。但编程人员经常容易忘记释放这些资源,从而造成一些事故。Go 语言直接在语言层面提供 defer 关键字,在申请资源语句的下一行,可以直接用 defer 语句来注册函 数结束后执行释放资源的操作。因为这样一颗小小的语法糖,忘写关闭资源语句的情况就大大地减 少了。
GO 逃逸分析
  • go语言编译器会自动决定把一个变量放在栈还是放在堆,编译器会做逃逸分析(escape analysis), 当发现变量的作用域没有跑出函数范围,就可以在栈上,反之则必须分配在堆。
  • Golang中一个函数内局部变量,不管是不是动态new出来的,它会被分配在堆还是栈,是由编译器做逃 逸分析之后做出的决定。 按理来说, 人家go的设计者明明就不希望开发者管这些,但是面试官就偏偏找这种问题问? 醉了也是
  • 命令:go build -gcflags="-m" main.go
make与new的异同
  • make: 只用于slice、map以及channel的初始化, 无可替代
  • new: 用于类型内存分配(初始化值为0), 不常用
  • make返回的还是这三个引用类型本身;而new返回的是指向类型的指针
select,poll,epoll区别
  • 当前进程的所有描述符一次拷贝到内核,内核会根据描述符的类型,调用对应的系统调用,然后返回结果
  • 内核快速无差别的遍历每个fd,判断是否有数据到达
  • 将所有fd拷贝到用户态,并通知已就绪fd个数
  • 用户态自己遍历fd,进行相应的事件处理
  • select不足:
  • 文件描述符bitmap有长度限制,一般1024个
  • 频繁用户太和内核态切换,资源开销较大
  • 需要对fd进行遍历,效率低
  • poll:
  • 定义poll_fd结构体,无1024描述符限制
  • epoll:
  • poll_fd结构体改为epoll_event结构体
  • epoll_ctr为每个fd指定了回调函数,时间复杂度O(1)
  • epoll使用树结构,对fd进行排序,方便快速查找,提高效率
查看go源码命令,反编译
  • go tool compile -S -N -l main.go
go循环语句,为什么不使用uint?

*

尽管Go语言提供了无符号数的运算,但即使数值本身不可能出现负数,我们还是倾向于使用有符号的int类型,就像数组的长度那样,虽然使用uint无符号类型似乎是一个更合理的选择。事实上,内置的len函数返回一个有符号的int,我们可以像下面例子那样处理逆序循环。

medals := []string{"gold", "silver", "bronze"}
for i := len(medals) - 1; i >= 0; i-- {
fmt.Println(medals[i]) // "bronze", "silver", "gold"
}

另一个选择对于上面的例子来说将是灾难性的。如果len函数返回一个无符号数,那么i也将是无符号的uint类型,然后条件i >= 0则永远为真。在三次迭代之后,也就是i == 0时,i--语句将不会产生-1,而是变成一个uint类型的最大值(可能是$2^64-1$),然后medals[i] 表达式运行时将发生panic异常(§5.9),也就是试图访问一个slice范围以外的元素。

GO协程可能引发哪些问题
  • 死锁
  • 数据同步问题count++
  • 闭包问题,for循环里打印迭代标量,实际上是同一份数据
  • 协程阻塞
多个服务读取一份数据,如何保证数据正确
  • 分布式锁
  • 消息队列
  • 数据库锁
go内存四区
  • 栈:空间较小,要求数据读写性能高,数据存放时间较短暂。由编译器自动分配和释放,存放函数的参数 值、函数的调用流程方法地址、局部变量等
  • 堆:空间充裕,数据存放时间较久。一般由开发者分配及释放(但是Golang中会根据变量的逃逸现象来选择 是否分配到栈上或堆上),启动Golang的GC由GC清除机制自动回收
  • 全局变量区
  • 代码区:存放函数的指令,由编译器自动分配,一般不需要手动管理

results matching ""

    No results matching ""