记录一些GO的常见问题

###空struct{} 的使用

空结构体 struct{} 可以用来节省内存
  • 空结构体的特点:1、不占用内存;2、地址不变

  • 如果使用的是map,而且map又很长,通常会节省不少资源

  • 空struct{}也在向别人表明,这里并不需要一个值

比较

####结构体的比较

  • 如果结构体的所有成员变量都是可比较的,那么结构体就可比较

  • 如果结构体中存在不可比较的成员变量,那么结构体就不能比较

####struct可以作为map的key么?

  • struct必须是可比较的,才能作为key,否则编译时报错

####interface的比较

  • 接口值可以用 == 和 != 相比较。两个接口值相等,仅当他们都是nil,或者他们动态类型相同,并且动态的值也根据这个动态类型的==相等。

Golang不可以比较类型:

  • slice(切片)、map(key-value集合)、func(函数),当接口的原始类型是这三个的时候,比较会报panic。

TCP和UDP的区别及应用场景

  • tcp有流量控制,udp没有
  • tcp的头部比20bytes,udp8byres
面向连接VS无连接
  • TCP建立一个连接需要3次握手IP数据包,断开连接需要4次握手。另外断开连接时发起方可能进入TIME_WAIT状态长达数分钟(视系统设置,windows一般为120秒),在此状态下连接(端口)无法被释放。
  • UDP不需要建立连接,可以直接发起。
可靠VS不可靠

TCP利用握手、ACK和重传机制,udp没有。

  • 校验和(校验数据是否损坏);
  • 定时器(分组丢失则重传);
  • 序列号(用于检测丢失的分组和重复的分组);
  • 确认应答ACK(接收方告知发送方正确接收分组以及期望的下一个分组);
  • 否定确认(接收方通知发送方未被正确接收的分组);
  • 窗口和流水线(用于增加信道的吞吐量)。(窗口大小:无需等待确认应答而可以继续发送数据的最大值)

有序性

  • TCP利用seq序列号对包进行排序,udp没有。

面向字节流vs面向报文

  • 面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。(一个upd的最大报文长度2^16-1-20-8,20是ip报文头,8是udp报文头)

  • 面向字节流的话,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。

应用场景

  • TCP:效率要求相对低,但对准确性要求相对高的场景。因为传输中需要对数据确认、重发、排序等操作,相比之下效率没有UDP高。举几个例子:文件传输(准确高要求高、但是速度可以相对慢)、接受邮件、远程登录。

  • UDP:效率要求相对高,对准确性要求相对低的场景。举几个例子:QQ聊天、在线视频、网络语音电话(即时通讯,速度要求高,但是出现偶尔断续不是太大问题,并且此处完全不可以使用重发机制)、广播通信(广播、多播)。

select是随机的还是顺序的?

select会随机选择一个可用通道做收发操作

Go语言局部变量分配在栈还是堆?

Go语言编译器会自动决定把一个变量放在栈还是放在堆,编译器会做逃逸分析,当发现变量的作用域没有跑出函数范围,就可以在栈上,反之则必须分配在堆。