Golang 从入门到放弃 -0x15

Web 中间件、handler/service/repository 分层,以及接口代码怎么写得不乱。

前面我们已经能写最基本的 HTTP 服务了,但只要接口一多,你很快就会发现,一个 main.go 里堆满所有 handler 的写法,读起来像在翻杂货铺。这一章我们把 Web 服务稍微整理得像样一点:中间件、路由、分层。

中间件到底是什么

可以先把中间件理解成“包在 handler 外面的一层公共逻辑”。比如日志、鉴权、recover、统计耗时,这些都不应该每个接口手抄一遍。

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        log.Printf("%s %s %s", r.Method, r.URL.Path, time.Since(start))
    })
}

有了这个之后,所有请求经过它时都会自动记日志。

给 handler 套上中间件

mux := http.NewServeMux()
mux.HandleFunc("/ping", pingHandler)

handler := loggingMiddleware(mux)
http.ListenAndServe(":8080", handler)

如果后面再叠一层 recoverMiddleware、authMiddleware,本质上也是一层一层包起来。

别把所有逻辑都塞进 handler

这是后端新手非常容易踩的一个坑。接口函数里既解析参数、又写 SQL、又拼 JSON、又处理业务判断,最后 200 行糊成一锅粥。

一个更舒服的思路是分层:

  • handler:收请求、回响应
  • service:写业务逻辑
  • repository:跟数据库打交道

这样出问题时你至少知道该往哪层找,而不是在一个大函数里摸黑。

一个简单的例子

type UserService struct {
    repo *UserRepo
}

func (s *UserService) GetUser(ctx context.Context, id int) (*User, error) {
    return s.repo.FindByID(ctx, id)
}

func userHandler(svc *UserService) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        user, err := svc.GetUser(r.Context(), 1)
        if err != nil {
            http.Error(w, "internal error", http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(user)
    }
}

这还不算大项目,但已经比“所有东西都写在 handler 里”清楚很多了。

公共响应别每次手搓

如果你的接口越来越多,建议抽一点小工具出来,比如统一写 JSON 响应。

func writeJSON(w http.ResponseWriter, status int, data any) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(status)
    json.NewEncoder(w).Encode(data)
}

别小看这种小函数。多几个接口以后,你会感谢它的。

小结

这一章主要是在帮你的 HTTP 服务摆脱“越写越乱”的命运:

  • 中间件负责公共横切逻辑。
  • handler 只做入口层的事,不要什么都往里塞。
  • service / repository 分层能让代码更好找、更好改。
  • 公共响应格式可以抽成小工具。

下一章我们讲部署和 Docker。毕竟代码写完只是第一步,能不能稳稳跑起来,才算真正交活。

Read more

Harness Engineering:从驾驭模型到构建 AI 工厂

Harness Engineering:从驾驭模型到构建 AI 工厂

2026 年,AI 编程工具的竞争焦点发生了根本性转变:决定 AI 助手好不好用的,不再是模型本身,而是包裹在模型外面的那层"Harness"。同一个模型,在不同的 Harness 下,性能差距可以达到 78% vs 42%。 这篇文章将带你深入了解 Harness Engineering——这个正在重新定义 AI 工程实践的新兴领域。 一、什么是 Harness Engineering? Harness 的字面意思是"马具/缰绳"——用来驾驭一匹强壮但不受控的马。在 AI 语境下,Harness 就是 LLM 之外的一切:工具定义、记忆系统、权限模型、反馈循环、文档规范、多

By Fuyu Jia

Claude Code CLI + Ralph:让 AI 自动完成大型编程任务的终极方案

TL;DR 当你的编程任务大到一个 AI 对话窗口装不下时,Ralph 会帮你把任务拆成小块,让 Claude Code CLI 一个接一个地自动完成——每轮都用全新的上下文窗口,不会越写越糊涂。 一、什么是 Ralph? Ralph 是一个开源项目(GitHub 16k+ Stars),基于 Geoffrey Huntley 提出的 "Ralph Pattern" 构建。它的核心理念很简单: 不要让 AI 在一个漫长的会话里做完所有事情,而是把大任务拆成小故事,每个故事用一个全新的 AI 实例来完成。 这解决了 AI 编程中最常见的痛点——上下文窗口耗尽。当对话越来越长,AI 的输出质量会明显下降。Ralph 通过「每轮一个新实例」的方式,

By Fuyu Jia