Golang 从入门到放弃 -0x0E

用 net/http 写最小 Web 服务,处理参数、返回 JSON,并组织基本路由。

铺垫了这么多章,终于可以写点像样的服务了。别急着上 gin、gorm、各种脚手架,这一章我们先用 Go 自带的 net/http 搭一个最小可用的 Web 服务。先把原理摸清,后面你用什么框架都不至于一脸懵。

一个最简单的 HTTP 服务

package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "hello golang")
}

func main() {
    http.HandleFunc("/hello", helloHandler)
    fmt.Println("server running at :8080")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        fmt.Println(err)
    }
}

跑起来后,浏览器访问 http://127.0.0.1:8080/hello,就能看到输出。

这里有两个核心点:

  • http.HandleFunc 注册路由
  • http.ListenAndServe 启动服务

处理请求参数

假设我们想从查询字符串里拿一个名字。

func helloHandler(w http.ResponseWriter, r *http.Request) {
    name := r.URL.Query().Get("name")
    if name == "" {
        name = "anonymous"
    }
    fmt.Fprintf(w, "hello, %s\n", name)
}

这时访问:

http://127.0.0.1:8080/hello?name=Raymond

就会得到:

hello, Raymond

返回 JSON

后端更常见的工作不是吐一行文本,而是返回 JSON。这个时候就轮到前一章的知识上场了。

package main

import (
    "encoding/json"
    "net/http"
)

type Resp struct {
    Message string `json:"message"`
    Code    int    `json:"code"`
}

func pingHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    resp := Resp{
        Message: "pong",
        Code:    0,
    }
    json.NewEncoder(w).Encode(resp)
}

这里我用了 json.NewEncoder(w).Encode(resp),因为它很适合直接把对象写进响应体里。

根据请求方法区分逻辑

很多接口会区分 GETPOST 等方法。你完全可以自己判断。

func userHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
        http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
        return
    }

    w.Write([]byte("user list"))
}

http.Error 是个挺顺手的小工具,能顺便帮你把状态码和错误文本一起回出去。

完整一点的示例

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type Response struct {
    Message string `json:"message"`
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
    name := r.URL.Query().Get("name")
    if name == "" {
        name = "guest"
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(Response{
        Message: "hello, " + name,
    })
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/hello", helloHandler)

    fmt.Println("server running at :8080")
    if err := http.ListenAndServe(":8080", mux); err != nil {
        fmt.Println(err)
    }
}

这时候你用 curl 测一下:

curl "http://127.0.0.1:8080/hello?name=go"

返回大概会是:

{"message":"hello, go"}

小结

到这里,你已经能用 Go 写出一个最基础的 HTTP 服务了。虽然离生产环境还很远,但轮子已经开始滚起来了。

  • HandleFunc 注册处理函数。
  • ListenAndServe 启动服务。
  • 请求参数从 r 里拿,响应通过 w 写回去。
  • 返回 JSON 时,json.NewEncoder 很顺手。

如果这个系列继续往后写,下一步差不多就是数据库、测试、日志、配置、部署这些工程化内容了。到那时,你写出来的东西就不只是“能跑”,而是开始有一点“能上线”的味道了。

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