Skip to content

Instantly share code, notes, and snippets.

@Eminlin
Last active July 22, 2026 10:52
Show Gist options
  • Select an option

  • Save Eminlin/3063dcbf00124d17aba8af7f03bc13e0 to your computer and use it in GitHub Desktop.

Select an option

Save Eminlin/3063dcbf00124d17aba8af7f03bc13e0 to your computer and use it in GitHub Desktop.
gaolingtech-note

1. 请设计一套 Go 企业级项目目录结构,并说明各层职责。要求支持微服务、DDD、可测试、可扩展。

/cmd 函数入口
--/app_1
--/app_2
--/crontab
/bootstrap 项目依赖启动,统一管理,不分散init
/configs 项目配置文件
/docs rpc规定文件、项目介绍文档
/gen rpc生成工具
/internal 
--/middleware 中间件
--/models 结构体定义
--/handler 控制器,参数解析
--/service
----/order 订单服务
----/user 用户服务
--/router 路由管理
/server 管理不同协议启动的入口
--/http
--/websocket
--/rpc
--/mqtt
/pkg
-- /logger 自定义日志包
-- /database 数据库连接方法,参数传入连接信息
-- /errors 错误码管理
-- /thirdpary 第三方服务
/logs 存放日志信息

DDD需要拆分模块通信。

2. 请设计一套统一的错误码体系(Error Code),要求支持:HTTP、gRPC、内部错误、第三方错误、国际化、前端展示。

枚举错误码:

const (
	// ValidateErr 校验错误
	ValidateErr = iota + 40000

	// RequireAuthErr 没有权限
	RequireAuthErr

	// NotFoundErr 没有记录
	NotFoundErr
  ...
)

错误信息关键结构体

type bizErrWithCode struct {
	code  int
	msg   string
	cause error
}


func Wrap(err error, code int, msg string) error {
	if err == nil {
		return nil
	}
	if e, ok := err.(*bizErrWithCode); ok {
		return &bizErrWithCode{
			code:  e.code,
			msg:   msg,
			cause: err,
		}
	}
	return &bizErrWithCode{
		code:  code,
		msg:   msg,
		cause: err,
	}
}

Wrap 可以调用第三方包的i18配置,解析国际化配置文件信息

3. 请设计一套统一日志方案,要求支持:TraceID、RequestID、UserID、TenantID、链路追踪、日志脱敏、日志采样。

使用dfs算法,配合Go反射,匹配结构体类型,解析需要过滤的字段filterPhoto,过滤敏感字段

// sep 替换字符
const sep = "."

// MaxDepth 最大匹配深度
const MaxDepth = 8

// 需要匹配的字段
const (
	filterPhoto = ".payload.params.photo" //微信上传的
)

单例模式开启日志记录,定义结构体,包含TraceID、RequestID、UserID、TenantID字段,通过context传递部分信息,转json存储

// 小写开头 单例获取
var iLog *logrus.Logger

// InitLog 交付给 bootstrap 初始化
func InitLogger() {
	iLog = newLog("log/debug")
}

// newLog 新建日志对象
func newLog(logpath string) *logrus.Logger {
	// 实例化
	logger := logrus.New()
  ...
}

8. 如何保证 Go 项目在多人协作开发过程中代码风格统一、质量可控?

  • gofmt,强制格式化
  • 增加.golangci.yml配置,pre-commit自动检查
  • 代码审核的时候检查,统一规范文档

9. 请设计一套多租户(Multi-Tenant)数据隔离方案,要求开发人员无需手动传递 tenant_id。

http层,中间件解析,根据登录信息,context 自动携带 TenantID,Repository、Service层可以通过 context 传递读取 gorm,可以注入Scope兜底

func TenantScope(ctx context.Context) func(db *gorm.DB) *gorm.DB {
    return func(db *gorm.DB) *gorm.DB {
        tenantID := tenancy.MustTenantID(ctx)
        return db.Where("tenant_id = ?", tenantID)
    }
}

10. 如何设计一套 RBAC 权限系统,同时支持:超级管理员、平台管理员、企业管理员、普通用户、数据权限。

成熟方案:Go,Casbin

RBAC(Role-Based Access Control,基于角色的权限控制)是一种通过角色将用户和权限连接起来的权限管理方法

用户表、角色表、接口表、角色接口权限表

11. 请设计一套接口幂等方案,适用于:创建订单、支付、回调通知、MQ 消费。

支付必须以 支付单号 为核心幂等键

创建订单,防止重复创建,请求携带nonce,中间件5分钟过期+订单创建前检查

  1. 查询订单是否已支付
  2. 查询是否已有支付单
  3. 没有则创建 payment_no

MQ消费,需要建立消费表,保障消息不会重复消费、投递成功,和订单表处理时,携带事务。

15. 如何设计一套高并发库存扣减方案?

1、前端抢购锁定按钮,不要重复触发 2、redis库存预扣减 3、MQ异步创建订单落库

request_id + tenant_id + sku_id + order_id 保持幂等

死信队列做超时未支付处理

20. 如何保证数据库与缓存的数据一致性?

  1. 先查缓存
  2. 缓存命中,直接返回
  3. 缓存未命中,查数据库
  4. 数据库结果写入缓存
  5. 返回数据

24. 如何定位 Go 程序中的 Goroutine 泄漏问题?

import _ "net/http/pprof"

go func() {
    http.ListenAndServe("127.0.0.1:6060", nil)
}()

curl -o goroutine-1.txt http://127.0.0.1:6060/debug/pprof/goroutine?debug=2

25. 请说明 Go 中 Context 的最佳实践,并列举哪些数据适合放入 Context,哪些不适合。

1、数据的上下层传递,链路追踪 2、超时关闭整条链路

大对象不适合通过context传递

27. 如何保证生产环境发布过程零停机?

1、发布migration,数据库表版本自动更新 2、蓝绿版本,nginx平滑重启 3、docker容器平滑重启

31. 目前你主要使用哪些 AI 编程工具?分别应用于哪些开发场景?

编码模型:Codex/GPT、Claude

33. 如果让 AI 参与企业项目开发,你认为哪些环节必须由人工 Review?

  • 数据库的所有操作
  • 订单数据的所有操作,涉及金融金钱的修改
  • 写文件的操作
  • 用户敏感信息的操作

36. 如果让你在三个月内重构一个已有五年历史的 Go 系统,你会如何制定实施计划?

曾经在3个月内重构了3年历史的Go项目

优先保障业务运行,日常的迭代开发。闲暇时间,根据业务影响情况,优先拆分杂糅的目录结构。通过新的脚手架目录,先完成外部流量的引导。然后再逐步拆分项目,完成重构。

38. 如果新项目允许自由选择技术栈,你会如何进行技术选型?请列出你的评估维度。

团队整体技术水平情况,是否选用Gin,goMicro,是否微服务拆分

人员少情况:单体服务,monorepo,不拆分微服务,不使用DDD,优先使用Gin等框架 人员多,且跨部门开发语言不一致,使用RPC拆分 人员多,且负责业务不一样,使用微服务拆分,选用效率高的,支持面广的技术框架,例如Thift

39. 如果系统必须在一周内上线,但存在部分技术债务,你会如何权衡开发速度与代码质量?

优先保障业务上线,技术债务根据影响面情况解决,如果影响整体进度,影响交付的,则会上提出需要解决

如果业务影响面小,回报效益大的,可以处理优化任务

40. 请列举近一年对你影响最大的三项技术或工具,并说明它们对你的工作带来的改变。

一年内,肯定就是 Claude GPT等这些大模型了,编码模式全部变了,以往要手敲代码,现在是复古程序员了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment