Golang 从入门到放弃 -0x0B

JSON 编解码、文件读写与配置读取,把基础能力串到一起用。

写后端绕不开两件事:一件是和 JSON 打交道,另一件是和文件打交道。这一章把它们放一起讲,因为这俩往往会在真实项目里结伴出现,比如读配置、写日志、导入导出、接口收发数据,全都离不开它们。

先看 JSON

Go 标准库已经把 JSON 处理准备好了,常用的是 encoding/json

先定义一个结构体:

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

这里的 tag 开始派上用场了。结构体字段名是大写开头,为了能被包外和 JSON 包访问;而 tag 决定了序列化后的字段名。

结构体转 JSON

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    user := User{Name: "Raymond", Age: 18}
    data, err := json.Marshal(user)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(data))
}

输出大概是:

{"name":"Raymond","age":18}

如果你想让它更好看一点,用 json.MarshalIndent

data, _ := json.MarshalIndent(user, "", "  ")
fmt.Println(string(data))

JSON 转结构体

raw := []byte(`{"name":"Tom","age":20}`)
var user User
err := json.Unmarshal(raw, &user)
if err != nil {
    fmt.Println(err)
    return
}
fmt.Println(user.Name, user.Age)

注意这里要传指针 &user,因为 Unmarshal 需要把结果写回你的变量里。

omitempty 也很常见

有些字段为空时你不想让它出现在 JSON 里,可以这么写:

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age,omitempty"`
}

这在接口响应里很常见,省一点无意义字段,报文会干净些。

读文件

再来看文件 I/O。现在标准库里最顺手的方式之一,是 os.ReadFileos.WriteFile

content, err := os.ReadFile("config.json")
if err != nil {
    fmt.Println(err)
    return
}
fmt.Println(string(content))

如果你是从一些旧教程里学到的 ioutil.ReadFile,先别紧张,它以前确实存在,只是现在已经不推荐了。

写文件

data := []byte("hello go")
err := os.WriteFile("demo.txt", data, 0644)
if err != nil {
    fmt.Println(err)
}

最后那个 0644 是文件权限,Linux 同学看着会比较亲切,Windows 下你暂时知道这个参数要填就行。

组合起来:读配置文件

把 JSON 和文件 I/O 合起来,就是一个非常常见的配置读取场景。

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type Config struct {
    Host string `json:"host"`
    Port int    `json:"port"`
}

func main() {
    content, err := os.ReadFile("config.json")
    if err != nil {
        fmt.Println("读取失败:", err)
        return
    }

    var cfg Config
    err = json.Unmarshal(content, &cfg)
    if err != nil {
        fmt.Println("解析失败:", err)
        return
    }

    fmt.Printf("服务启动在 %s:%d\n", cfg.Host, cfg.Port)
}

这已经很接近真实项目里的样子了。你会发现,前面学的结构体、函数、错误处理,到这里都开始串起来用了。

小结

这一章很实用,建议你至少自己敲一遍:

  • json.Marshal:结构体转 JSON。
  • json.Unmarshal:JSON 转结构体。
  • os.ReadFile / os.WriteFile:读写文件。
  • tag 决定 JSON 字段怎么映射。

下一章开始讲 goroutine。终于轮到 Go 最喜欢拿出来做广告的那部分了。

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