2022-12-01 22:56:12
接口原理、用法及作用
原理:Go接口是隐式实现的,通过定义方法集合(方法签名)描述行为,类型通过实现接口所有方法自动满足接口。接口变量底层是iface结构体,包含指向类型信息的指针和指向数据指针的指针。
用法:定义接口类型(如type Reader interface { Read([]byte) (int, error)}),类型实现接口方法后可直接赋值给接口变量。
作用:解耦代码、实现多态、支持依赖注入,例如标准库io.Reader/Writer抽象I/O操作。
多线程、进程、协程
进程:资源分配单位,拥有独立内存空间,进程间通信(IPC)需通过管道、共享内存等。
线程:CPU调度单位,共享进程内存,但切换开销大(涉及寄存器、栈保存)。
协程(Goroutine):用户态轻量级线程,由Go运行时调度,栈初始小(2KB),动态扩容,切换成本低(仅保存PC/SP)。
数据库索引:哈希索引 vs B+树索引
哈希索引:
适合等值查询(如=、IN),不支持范围查询。
底层为哈希表,冲突时用链表解决,O(1)时间复杂度。
示例:MySQL的MEMORY引擎支持哈希索引。
B+树索引:
适合范围查询(如>、BETWEEN),数据有序存储。
非叶子节点存键值指针,叶子节点存数据或主键,通过指针连接形成有序链表。
示例:InnoDB默认使用B+树索引。
适合加索引的字段:高频查询条件、排序字段、连接字段;低选择性字段(如性别)不适合。
new vs make
new:分配内存并零值初始化,返回指针(如p := new(int),*p为0)。
make:仅用于内置类型(slice、map、channel),初始化底层数据结构并返回引用(如s := make([]int, 5))。
值传递 vs 引用传递
值传递:基本类型(int、float等)、数组(非切片)、结构体(非指针)传递副本,修改不影响原值。
引用传递:指针、切片、map、channel、函数、接口传递引用,修改会影响原值。
场景:大结构体用指针避免拷贝开销;需修改原值时用指针。
堆与栈分配
栈分配:局部变量、函数参数等生命周期明确的变量,由编译器自动分配/释放,速度快。
堆分配:逃逸到函数外的变量(如返回指针、闭包引用)、大变量(超过栈大小限制),由GC回收。
逃逸分析:编译器通过分析变量作用域决定分配位置,可通过go build -gcflags="-m"查看。
Channel读写流程
发送:若接收方存在且队列未满,直接拷贝数据到接收方栈;否则阻塞或触发调度。
接收:若发送方存在且队列有数据,直接拷贝数据;否则阻塞或触发调度。
底层结构:hchan结构体包含缓冲区、发送/接收队列、互斥锁等。
浏览器寻址URL过程
解析URL,提取协议、域名、路径等。
检查本地DNS缓存,未命中则向DNS服务器发起递归查询。
建立TCP连接(三次握手),若使用HTTPS则进行TLS握手。
发送HTTP请求(GET/POST等),服务器返回响应。
浏览器渲染页面(解析HTML/CSS/JS)。
ARP表作用与分组格式
作用:维护IP到MAC地址的映射,用于局域网内数据帧转发。
分组格式:包含硬件类型(以太网为1)、协议类型(IPv4为0x0800)、硬件地址长度(6字节)、协议地址长度(4字节)、操作码(1请求/2响应)、发送方/目标方MAC/IP地址。
ARP请求处理
若目标IP不存在,主机丢弃请求且不响应;发送方超时后重试或报错。
DNS作用与解析流程
作用:将域名解析为IP地址。
流程:
检查本地hosts文件和DNS缓存。
向配置的DNS服务器(如8.8.8.8)发起查询。
递归查询:DNS服务器逐级向根域名服务器、顶级域名服务器、权威域名服务器请求,最终返回结果。
下一跳路由转发
路由器根据目标IP查找路由表,匹配最长前缀的条目确定下一跳IP和出接口。
若无匹配条目,丢弃数据包或发送到默认网关。
G(Goroutine):协程,用户态线程,包含栈、程序计数器等。
M(Machine):操作系统线程,绑定P执行G。
P(Processor):逻辑处理器,管理G队列,调度G到M执行。
线程由OS调度,协程由用户态调度器(如Go的GMP)调度。
线程切换开销大(需保存寄存器、内核态切换),协程切换轻量(仅保存PC/SP)。
P从本地队列或全局队列获取G。
将G绑定到M执行,若M阻塞(如系统调用),P解绑M并从线程池获取新M。
G执行完毕或主动让出CPU,P回收G并调度下一个。
P数量默认等于CPU核心数(可通过GOMAXPROCS调整),M数量动态伸缩(上限约10000)。
G主动调用runtime.Gosched()让出CPU。
G执行时间片耗尽(GO 1.14后引入协作式调度)。
G进行系统调用或通道操作阻塞时。
高性能(基于httprouter,路径匹配快)。
中间件支持(如日志、认证)。
简洁的API设计(链式调用)。
使用压缩前缀树(Radix Tree)存储路由路径,支持静态路由、参数路由(:name)、通配路由(*filepath)。
匹配时从根节点开始,按路径分段查找,优先匹配最长前缀。
RPC vs HTTP:
RPC:面向服务,支持多种协议(如gRPC的HTTP/2),性能高(二进制编码),适合内部服务调用。
HTTP:通用性强,支持RESTful API,适合跨语言/跨平台调用。
PB协议快的原因:
二进制编码(JSON为文本编码,体积大)。
预定义Schema,无需解析键名。
支持高效序列化(如proto.Marshal)。
HTTP/2 vs HTTP/1.1:
HTTP/2:多路复用(单连接并行请求)、头部压缩、服务器推送。
HTTPS vs HTTP:
HTTPS:HTTP + TLS/SSL,加密传输,防篡改/窃听。
gRPC底层协议:基于HTTP/2,使用PB编码。
MySQL存储引擎:
InnoDB:支持事务、行级锁、外键,默认引擎。
MyISAM:不支持事务,表级锁,适合读多写少场景。
Memory:数据存内存,速度快,重启丢失。
事务特性与隔离级别:
ACID:原子性、一致性、隔离性、持久性。
隔离级别:
读未提交(可能脏读)。
读已提交(解决脏读,可能不可重复读)。
可重复读(MySQL默认,解决不可重复读,可能幻读)。
串行化(最高隔离,性能最低)。
Redis快的原因:
内存存储,单线程处理命令(避免锁竞争)。
IO多路复用(epoll/kqueue)。
数据结构高效(如跳表、压缩列表)。
Redis常用数据结构:
ZSET:跳表+哈希表实现,支持范围查询和排序。
Redis网络模型:单线程Reactor模式,基于ae事件库处理连接和命令。
使用Redis Pub/Sub或RabbitMQ实现消息广播。
负载均衡(Nginx)分配连接至不同节点。
RabbitMQ:轻量级,支持多种协议(AMQP),适合低延迟场景。
Kafka:高吞吐,磁盘持久化,适合日志处理,但内存占用高(因缓存和索引)。
CPU:top、htop、mpstat -P ALL 1。
内存:free -h、vmstat 1。
基于net/http的Handler链,通过context.Context传递数据。
内存占用取决于中间件数量和请求上下文大小。
支持链式查询(如Where().Order().Limit())。
事务管理(Begin()/Commit()/Rollback())。
多级缓存(本地缓存+Redis)。
缓存击穿/雪崩防护(互斥锁、随机过期时间)。
监听文件变化(fsnotify),重新编译并重启服务(如air工具)。
主键选择(自增ID/UUID)、外键约束、索引优化。
Raft:强一致性,用于分布式共识(如etcd)。
Gossip:最终一致性,用于服务发现(如Consul)。