【Go Interface】接口诞生的意义 结论接口Interface诞生的唯一意义解耦接口的诞生是为了解决软件工程里最致命的痛点“上层代码”被“底层细节”死死绑架。没有接口时的痛苦假设你的naga模块现在要保存心跳数据。第一周你用的是 Redis 缓存你在repo里写了一个结构体type RedisRepo struct{} func (r *RedisRepo) SaveHeartbeat(data string) { /* 写入 Redis */ }这时候你的上层业务逻辑logic层为了调用它就必须在结构体里死死绑定制冷工具type ServerLogic struct { Dao *RedisRepo // 致命痛点这里写死了 Redis } func (l *ServerLogic) Execute(data string) { l.Dao.SaveHeartbeat(data) }灾难来了第二周老板说 Redis 内存太贵了心跳必须改存到 MySQL 数据库里你高高兴兴写完了MySQLRepo回头一看ServerLogic你当场就崩溃了——因为里面写死了*RedisRepo你必须把整个logic层全部翻出来把类型改成*MySQLRepo。如果整个大系统有 50 个地方写死了 Redis你就得改 50 个地方。有了接口Interface后的降维打击接口的本质就是上层 logic 层对底层 repo 层下达的一份“悬赏通缉令契约”。Logic 层现在不当传话筒了它直接在自己的包里宣布“我不管你底层用 Redis、MySQL 还是机械硬盘只要谁能做到SaveHeartbeat(string)这个行为谁就可以来当我ServerLogic的打工仔”// 1. 定义一个接口只定义行为不定义数据 type HeartbeatSaver interface { SaveHeartbeat(data string) } // 2. Logic 层现在只绑定这个抽象的“悬赏令”不绑定任何具体数据库 type ServerLogic struct { Dao HeartbeatSaver // 奇迹发生了这里是一个接口类型 }现在你的RedisRepo和MySQLRepo只需要老老实实实现SaveHeartbeat这个方法。想用 Redis直接把RedisRepo传给 Logic。想换 MySQLLogic 层的代码连一个标点符号都不用改直接把MySQLRepo传过去总结上层稳定的代码去适配底层多变的代码Interface 出现的意义就是让上层稳定不容易产生 Bug的代码去适配底层多变天天改需求的代码。 在大厂里只要涉及到“需要切换实现”如换数据库、换日志库、Mock 测试就必然会出现 Interface。