Go 语言仓储模式(Repository Pattern)落地指南

一、 核心架构图

仓储模式的核心思想是解耦业务底层存储。业务层通过接口与数据层交互,实现“铁打的业务,流水的技术”。

二、 标准目录结构

在 Go 项目中,通常结合 internal 目录限制外部非法引入,结构如下:

text
my-project/ ├── domain/ # 【领域层】最核心,完全纯粹,无外部技术/数据库依赖 │ ├── user.go # 用户实体、业务方法、以及 UserRepository 接口 │ └── errors.go # 领域层的通用业务错误(如 ErrUserNotFound) │ ├── internal/ # 【实现层】私有封装,防依赖污染,允许大胆重构 │ ├── repository/ # 仓储实现层 │ │ └── mysql_user.go # 实现 domain.UserRepository 接口,内含 GORM/SQL 逻辑 │ │ │ ├── service/ # 业务逻辑/应用层 │ │ └── user_service.go # 组合各种 domain 接口完成具体的业务流水线 │ │ │ └── delivery/http/ # 传输层/接口层(如 Gin 路由、HTTP Handler) │ └── handler.go │ └── main.go # 【入口】组装全局依赖(依赖注入),启动服务

核心原则

Agent 不可能完全避免报错,关键在于:

让错误可恢复(Recoverable)、可观测(Observable)、可控制(Controllable)。

标准处理流程:

text
报错发生 ↓ 识别错误类型 ↓ 判断是否可重试 ↓ 自动修复或降级 ↓ 记录日志 ↓ 必要时转人工

GPM模型

  • G:go中的协程
  • M: 系统线程,真正执行go代码的地方
  • P:调度上下文,保存本地G队列以及调度运行所需的资源,M必须绑定一个P 才能执行go代码 在Go中,线程是运行goroutine的实体,调度器的功能是把可运行的goroutine分配到工作线程上 image.png
  1. 全局队列(Global Queue):存放等待运行的G。
  2. P的本地队列:同全局队列类似,存放的也是等待运行的G,存的数量有限,不超过256个。新建G'时,G'优先加入到P的本地队列,如果队列满了,则会把本地队列中一半的G移动到全局队列。
  3. P列表:所有的P都在程序启动时创建,并保存在数组中,最多有GOMAXPROCS(可配置)个。
  4. M:线程想运行任务就得获取P,从P的本地队列获取G,P队列为空时,M也会尝试从全局队列拿一批G放到P的本地队列,或从其他P的本地队列偷一半放到自己P的本地队列。M运行G,G执行之后,M会从P获取下一个G,不断重复下去。 image.png

面试总结

面试介绍总结:百度poi商业化数据清洗平台(架构级别描述)

项目描述 or 项目定位

主要负责地图 商业化POI 数据清洗,平台整体是一个多阶段的数据处理流水线。数据以文件形式在各个处理环节之间流转,每一步都会读取上一步的结果文件进行处理,并生成新的结果文件。整个流程包括数据请求、结构解析、diff判断、策略判重、人工审核以及数据上线等

做了哪些数据库相关的优化

  • 性能优化

    • 解决数据量激增需要面临的分库分表问题
      • 从mysql迁移到百度的gaiaDB,增加读写分离
        • 增加只读节点
          • 把大量查询请求从 RW(Read Write)节点分流出去,
          • 让 RW 专注于写事务和少量必须读取最新数据的查询,
          • 从而提升整个集群的吞吐能力
  • gaiaDB优势:

    • 通过数据库代理统一管理连接池、读写分离、故障切换、读写分离
    • 无需分库分表
    • 采用存储和计算分离架构,单实例最大数据量超 500TB,存储自动扩容
    • 支持列存索引,实现复杂查询性能相比MySQL提升100倍以上
    • 支持按需扩展、按需付费,综合成本降低50%
  • 索引优化

    • explain 判断是否使用索引、索引类型、扫描多少行、连接方式、是否需要排序、是否使用临时表等。
      • type 的常见值
      type含义好坏
      const主键唯一查询⭐⭐⭐⭐⭐
      eq_ref主键关联⭐⭐⭐⭐⭐
      ref普通索引⭐⭐⭐⭐
      range范围查询⭐⭐⭐
      index全索引扫描⭐⭐
      ALL全表扫描
      • key 使用了那个索引
      • extra
        • use index
        • use where
        • use tempory
        • use filesort
  • sql优化

    • 接口响应优化从23s到 300ms的实现
    • sql LIMIT offset, size查询导致的频繁扫表问题
2026-04-220

LRU 算法实现

题目要求

golang 实现lru算法,要求在 O(1) 时间内完成get和put请求

最长连续序列实现

题目

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

js示例
输入: nums = [100,4,200,1,3,2] 输出: 4 解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。 示例 2: 输入: nums = [0,3,7,2,5,8,4,6,0,1] 输出: 9 示例 3: 输入: nums = [1,0,1,2] 输出: 3
2026-04-160

这里eino 框架学习的相关总结,方便后续学习和记忆

组件

  • ChatModel‌:与大模型交互的核心组件,支持生成式对话(Generate)和流式输出(Stream),部分实现还支持工具调用(ToolCallingChatModel)
  • Tool‌:扩展大模型能力的工具,可调用外部 API、数据库、文件系统等,支持同步(Invoke)和流式(Stream)两种范式
  • Retriever‌:从向量库或文档库中检索与查询相关的文档片段,常用于 RAG 场景。
  • Embedding‌:将文本转换为向量表示,用于语义搜索和向量索引。
  • Indexer‌:负责存储和索引文档向量,支持 Redis、Milvus 等向量数据库。
  • Document Loader‌:加载并解析多种格式的原始文档(如 PDF、Markdown、TXT 等),统一为schema.Document 结构。
  • Document Transformer‌:对文档进行切分、过滤或格式转换,如按标题、递归或语义切分。
  • ChatTemplate‌:管理提示词模板,支持 FString、GoTemplate、Jinja2 等语法,便于动态构建系统提示

从头开始,每K个一组,翻转链表

js
func main() { head := buildList([]int{1, 2, 3, 4, 5, 6}) k := 3 fmt.Println("原链表:") printList(head) newHead := reverseKGroup(head, k) fmt.Println("每K个翻转后:") printList(newHead) }