# 大染志
分享编程、运维、生活与思考

Junv's blog

## 时光荏苒呀

发表于 2025-10-27 更新于 2026-08-04

上一篇日志的时候我人还在成都，那一年的年底我就到了墨尔本，到现在都已经快8年了。

这8年变化太大了，我们经历了新冠疫情，在墨尔本买了房。定居下来。

从以前到微博，博客，到现在都抖音和小红书。再到这两年的大语言模型。

我也没想过这么快，AI几乎都可以写任何代码了，而且我上班每天都在用它，大量的用它。

## 使用 Caddy Web服务器显示 Markdown 文件

发表于 2017-10-12 更新于 2026-08-04

建议阅读此篇文章前，先阅读本博客的前篇 Caddy上手文章 ——【快速上手更简单的 Web 服务器 —— Caddy】

本篇文章我们将利用 Caddy Web 服务器的Markdown 插件和它强大的网页模板功能，在直接托管，渲染显示Markdown文件。

现在得益于 Markdown 的简单易用，越来越多的文档都在使用使用 Markdown来编写。像我们常用的 Github、GitBook 等流行服务也都在使用 Markdown。那么为什么越来越多的相关技术文档和资料都是使用 Markdown 编写的呢？我觉得所有原因都归于『简单』二字。我们通过一些常用的符号标记，就可以写出格式整齐、漂亮的文档。而不用写繁琐的 HTML。而通过简单的工具转化，我们就可以将 Markdown 文档转成 HTML 的格式。

## 安装 Caddy

那现在就让我们来实现这个功能吧，首先你得在你的电脑或者服务器上安装 Caddy，如何安装？请查看之前的文章进行回顾或直接运行如下脚本：

    1

    curl https://getcaddy.com | bash -s personal

## 初步渲染 Markdown

Markdown 作为 Caddy Web 服务器的标准指令，使得我们可以直接在 Caddyfile 配置文件中使用该指令，托管，渲染Markdown 文件。

    1
    2
    3
    4
    5

    0.0.0.0:8080 {
      markdown {
        ext .md .markdown
      }
    }

这里的配置是说：在我们希望托管 Markdown 文件的服务器地址块中，让服务器对当前目录启用渲染 Markdown 文件的功能，即当我们访问 Markdown 文件时，Caddy 自动将其转化为 HTML 进行展示。下面我将以为我本地的文件作为示例给大家展示效果和截图。

如图所示为 Caddyfile 所在目录。可以看到这里有若干子目录，和子目录下面的.md 文件。现在让我们运行 caddy。 在浏览器中访问 `http://localhost:8080/0.general/0.general.md`文件。可以看到效果如下：

Caddy 成功的将 Markdown文件以网页的形式进行展示，并且正确显示此了相应的格式和层次结构。但是这里有个美中不足之处，Caddy 渲染出的效果，不够美观。简单一点说，没有 CSS 修饰。

### 美化 Markdown 文件

那我们如何将Markdown 文件更加美观的展示呢？由于 Caddy 本身是使用 Golang 进行开发的，因此 Caddy 也将 Go 强大的模板功能提供给了用户。这里我们可以利用 Caddy 模板功能来美化 Markdown 文件。我们将在模板网页中加入特定 CSS 来美化页面。CSS 库来自： https://github.com/sindresorhus/github-markdown-css

在 Caddyfile 目录下创建一个叫 `template.html` 的网页文件，添加如下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    html>
    html>

    head>
      title>{{.Doc.title}}title>
      link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.8.0/github-markdown.css">
      style>
        .markdown-body {
          box-sizing: border-box;
          min-width: 200px;
          max-width: 980px;
          margin: 0 auto;
          padding: 45px;
        }
      style>
    head>

    body>
      div class="markdown-body">
        {{.Doc.body}}
      div>
    body>
    html>

我们的 Markdown 文本内容会在 `<div class="markdown-body">` 中显示。`github-markdown-css` 库会对类名为 `markdown-body` 中的内容进行美化。
`.Doc.title` 和 `.Doc.body` 则是网页模板中的动态内容，前者为文档的文件名，而后者为文档中的全部内容。与此同时，我们需要在 Caddyfile 配置文件中添加模板特性。
HTML 中而外的 `<style>`标签是为了，限制页面内容的宽度，和将内容居中显示。

    1
    2
    3
    4
    5
    6

    0.0.0.0:8080 {
      markdown {
        ext .md .markdown
        template template.html  #后面的值即为模板文件的文件地址
      }
    }

重启 Caddy 服务器，刷新页面。有没有觉得页面变得更加美观，漂亮了。

### 添加文档目录索引（TOC）

现在我们的 Markdown 文档已经可以很美观的进行展示了，但是我们还可以做得更好，让用户在第一屏就可以查看当前文档的目录索引，而且可以点击链接进行快速访问和跳转。 这就是我们常见的 TOC 功能。（Table of contents）

为了实现 TOC功能，我们需要引入两个 JS 库：

- jQuery， 由于 Caddy 在对 Markdown文档进行转化时，没有为h1,h2,h3 这样的标题添加 id属性，而我们的`<a>`链接跳转，正需要 id 属性。因此，我们需要手动为各级标题添加 id 属性。
- tocbot，该 JS 库可以自动生成 TOC 内容。

因此修改我们的网页模板成类似以下内容：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42

    html>
    html>
    head>
      title>{{.Doc.title}}title>
      script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js">script>
      script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/3.0.4/tocbot.min.js">script>
      link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/2.8.0/github-markdown.css">
      link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/3.0.4/tocbot.css" />
      style>
        .markdown-body {
          box-sizing: border-box;
          min-width: 200px;
          max-width: 980px;
          margin: 0 auto;
          padding: 45px;
        }
      style>
      script>
        $(document).ready(function () {
          //为各级标题自动生成id属性
          $("h1,h2,h3").each(function () {
            var hyphenated = $(this).text().replace(/\s/g, '-');
            $(this).attr('id', hyphenated);
          });
          // 初始化 toc 内容
          tocbot.init({
            tocSelector: '.toc', // 放置 toc 内容的容器
            contentSelector: '.markdown-body', // markdown 文档内容所在
            headingSelector: 'h1, h2, h3', // 需要索引的标题级别
            positionFixedSelector: ".toc" //将 toc 内容块位置固定。
          });
        });
      script>
    head>
    body>
      div class="toc">
      div>
      div class="markdown-body">
        {{.Doc.body}}
      div>
    body>
    html>

保存后，直接刷新页面。我们就可以看到带有 TOC 的 Markdown 文档了。

我们还可以试着访问下另外目录下的 Markdown 文件，可以看到所有 Markdown 文件都带有 TOC 和美观的样式了。

## 总结

所以，如果你不想把 Markdown文档放到 Github 或者使用 GitBook 来托管，可以试试这种方法，快速搭建一个基于 Caddy 服务器的 Markdown 文档的网站。

## 快速上手更简单的 Web 服务器 —— Caddy

发表于 2017-09-19 更新于 2026-08-04

说到Web 服务器，我们大多想到的是 Apache 这个老前辈和如日中天的Nginx，但是这里今天我将要分享的是 Web 服务器和反向代理服务器的新秀 Caddy。在我们拥有了这么强大的 Nginx 以后我们为什么还需要 Caddy？
我认为 Caddy 之所以可以占有一席之地是因为它的两大法宝：`配置简单` 和 `自动启用 HTTPS`。下面带下面快速上手这个软件。

## 安装

Caddy 提醒定制化的下载，可以自由选择各种插件和平台。请前往: https://caddyserver.com/download 下载。 也可以使用这个一键安装脚本：

    1

    curl https://getcaddy.com | bash

完成之后，我们可以尝试执行下`caddy -version`。 当你看到有有类似：`Caddy 0.10.9`，即表示安装成功。

## Hello World

在命令行里面直接输入`caddy`，然后打开浏览器输入： `http://ip:2015`。 看到什么了吗？ 你得到了一个404页面。Caddy 已经成功运行了。相比与其他浏览器需要各种配置文件才能运行相比，这就是 Caddy 的简单之处，不需要任何配置文件即可运行。当然当我们需要各种高级功能的时候，配置文件还是必不可少的。

默认情况下，Caddy 运行在`2015` 端口。我们可以可以 Caddy 强大的命令行工具来自定义运行端口。

    1

    caddy -p 80

在无配置文件的情况下，Caddy 默认是映射当前程序执行的目录所有文件。因此我们可以快速创建一个文件：

    1

    echo "Hello Caddy" >> index.html

再次刷新浏览器，刚才我们写的 `Hello Caddy` 已经出现在页面上了

## 强大的配置文件

Caddy 各种强大的功能还得需要 Caddyfile 体现。我们可以在任意目录放置我们的配置文件,通过命令行`caddy -conf` 即可指定

### Host 目录下的网页

    1
    2
    3

    0.0.0.0:8080 {
      root /usr/local/www/
    }

这里简单解释下，`0.0.0.0` 表示我们将网站绑定至可以访问到本机的任意一个 IP；`8080`表示我们将网站暴露在8080端口； `root` 参数则表示网站的根节点。这就是最简单的一个Host 网站的配置。

当前我们可以对网站添加更多的配置。比如设置响应过期时间，启用 gzip, 指定各种日志的输出端。

    1
    2
    3
    4
    5
    6
    7

    0.0.0.0:8080 {
      root /usr/local/www/
      timeouts 30s
      gzip
      log /var/log/caddy/access.log
      errors /var/log/caddy/error.log
    }

### 配置反向代理

什么时候你会需要反向代理呢？想象你有一个前后端分离的程序。前端是通过 JS 发送 Ajax 请求后端 API。默认情况下前端程序占用一个端口，后端占用一个另外端口。我们会遇到两个问题： CORS（跨域请求）和额外的 Options 请求。 这个时候我们就可以使用反向代理让前端和后端共享一个端口。

那怎么做呢，在 Caddy 里面也特别简单，假设我们的前端就是上面的那样，而我们的后面之前都运行在：`http://ip:4000` 下面。而且我们的 后端 API URL 里面都有 `/api`

    1
    2
    3
    4
    5

    0.0.0.0:8080/api {
        proxy / 127.0.0.0:4000/api {
            transparent
        }
    }

这里的配置的意思是说，当浏览器收到所有包含`:8080/api` 的请求都会自动转发到`127.0.0.1:4000/api` 这个地址，而`:8080/api` 后面的地址会自动转发下去，而`transparent` 这个设置保证了我们的转发不会在浏览器生成任何额外的`301` 或者`302`请求。

## 自动 HTTPS

Caddy 另外一个亮点就是，可以为已经`绑定域名`的在`公网`运行的服务器自动从 Let’s Encrypt生成和下载 HTTPS 证书，让你的网站支持 HTTPS 协议访问，保证网站数据传输的安全。很简单，你所需的仅仅是将绑定的 IP 改成域名。

    1
    2
    3

    xxx.com {
      root /usr/local/www/
    }

再次运行Caddy，按照提示输入你的 Email 之后。Caddy 会自动帮你获取并启用 HTTPS 证书。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    root@ss2:~# caddy -conf Caddyfile
    Activating privacy features...
    Your sites will be served over HTTPS automatically using Let's Encrypt.
    By continuing, you agree to the Let's Encrypt Subscriber Agreement at:
      https://acme-v01.api.letsencrypt.org/terms
    Please enter your email address so you can recover your account if needed.
    You can leave it blank, but you'll lose the ability to recover your account.
    Email address: xxxx@gmail.com
     done.
    https://xxx.com
    http://xxx.com

## 总结

通过上面的例子，我们可以看出 Caddy的快速上手能力和超级实用的 HTTPS 功能。除此之前 Caddy 还提供一大堆的插件供我们使用。比如直接访问 Markdown 文件、Host Git 仓库的文件、将自身 Metric 数据传到 Prometheus 等等。快去试试吧！

## 使用 VS Code 快速搭建你的 Golang 开发 IDE

发表于 2017-08-23 更新于 2026-08-04

说到 IDE 我们想到的都是 Intellij 和 Eclipse系列这样的几百兆的桌面应用程序，它让我们编程效率得以很大提升，在日常工作中变得离不开这些软件。我们最喜欢用的 IDE 功能主要有：

- 代码自动补全
- 代码重构
- 代码格式化
- 代码调试
- 代码高亮
- 代码错误检查
- 代码引用查询与跳转

但往往 IDE 也有占用内存多，时不时反应卡顿等问题。因此很多程序员在开发一些动态语言、脚本语言的时候更倾向于选择轻量级的文本编辑器软件。如：Sublime Text、Atom 、vscode（Visual Studio Code 简称 vscode）。其实不仅仅是动态语言或者脚本语言，现在的文本编辑器已经基本包含了上述 IDE 配置的功能了，除开在代码重构方面还落后甚远之外，其他功能点已经差别不大了。
纵观前两年最流行文本编辑器的还是 Sublime Text，而当下最新，最火热，最好用的我认为还得属于 vscode。为什么 vscode 能够在Sublime Text 和 Atom 两位前辈面前打下一片天地？如果用一个最大的优势来描述的话：

- 对于 Sublime Text， vscode 最大的优势是 UI 美观、功能全面，比如集成了代码调试、Git 代码变更查和更友好的插件安装功能
- 而相较于 Atom 而言，vscode 比它的同门师兄最大的优势则是快。

就我自己日常开发而言，除开 Java 以外，平时编写 Ruby、JavaScript、HTML、Vue.js、Golang、Markdown、Dockerfile 等语言都在使用 vscode。

在这篇文章中我不会再对为什么要用 VS Code 做过多解释。而是将介绍使用 vscode 快速搭建一个优秀的 Go (Golang) 的开发环境。

### 安装 vscode

说了 vscode 这么多好，如果你还不知道 vscode 是何物的话，这里简单介绍下。vscode 是微软基于 Electron 框架开发的跨平台的开源的文本编辑器。也许你曾用过它的兄弟 Visual Studio，被它的庞大和臃肿吓到，在这里却不用担心。vscode 是一个全新的项目，旨在打造一个轻量级、面向 Web 开发、稳定高效的开发平台。

你可以通过 https://code.visualstudio.com 官网下载安装 vscode软件

### 安装 Go 插件

#### 安装

vscode 之所以强大，其中很大一点便是因为它拥有庞大的插件对各个语言提供相关的功能。而对于 Go,官方提供了强大的插件 Go。你可以直接通过在插件页面，输入搜索 Go 进行安装相关插件，安装之后对 vscode 进行重启。该插件对 Golang 支持非常丰富的功能：

- 代码格式化
- 保存时代码自动格式化
- 自动添加 Imports
- 代码错误提示
- 引用查询与跳转到定义位置
- Go 代码元素搜索
- 文档查看
- 支持代码调试等等功能。

这些可以功能可以很好的满足我们日常开发所需。

#### 配置

Go 插件提供丰富的配置项，让我们对插件的默认行为进行调整，以便最大限度的适合每个人。
依次键入`F1` -> `Open User Settings` 即可打开vscode 用户配置文件，在文件末尾可以添加类似如下属性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    "go.buildOnSave": true, //在保存代码时自动编译代码
    "go.lintOnSave": true, //在保存代码时自动检查代码可以优化的地方，并给出建议
    "go.vetOnSave": true, //在保存代码时自动检查潜在的错误
    "go.buildTags": "",
    "go.buildFlags": [],
    "go.lintTool": "golint", //使用 golint 库来执行 lint操作，你也可以选择使用gometalinter
    "go.lintFlags": [],
    "go.vetFlags": [],
    "go.coverOnSave": false, //在保存代码时执行测试，并显示测试覆盖率
    "go.useCodeSnippetsOnFunctionSuggest": true, //使用代码片段作为提示
    "go.formatOnSave": true, //在保存代码时自动格式化代码
    "go.formatTool": "goimports", //使用 goimports 工具进行代码格式化，或者使用 goreturns和gofmt
    "go.formatFlags": [],
    "go.gocodeAutoBuild": true, //代码自动编译构建
    "go.goroot": "/usr/local/Cellar/go/1.8.3/libexec", //设置 goroot，正常编译 go 代码。
    "go.gopath": "/Users/junv/gocode:/Users/junv/mygocode", // 设置 gopath，有利于自动导入库

#### 使用

#### 调试 Go程序

打开 go 源码，在你期望调试的行号左侧，点击即可添加断点。
当你第一次进行调试时，vscode 则要求你添加调试程序的相关配置。可以输入类似下图的配置即可。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "monitor-api", //程序名字
                "type": "go",
                "request": "launch",
                "mode": "debug",
                "remotePath": "",
                "port": 1234,
                "host": "127.0.0.1",
                "program": "${workspaceRoot}",
                "env": {
                    "QUICKPAY_ENV": "testing" //注入你需要的环境变量
                },
                "args": []
            }
        ]
    }

点击开始按钮，即可进行Go 程序调试了。

#### 快速的搜索

当项目源代码越来越多，依赖的第三方库也越来越多的时候，你会发现 vscode的搜索功能 变慢了，而且很多时候我们并不希望搜索结果中包含 vendor （第三方依赖源代码）目录下的代码。
那么你可以尝试在`User Settings` 中添加如下的配置：

    1
    2
    3
    4
    5

    "search.exclude": {
      "**/node_modules": true,
      "**/bower_components": true,
      "**/vendor": true  //排除 vendor 目录
    },

这样 vscode 在执行搜索的时候就会跳过 vendor 目录下的文件，让搜索保持高效。

### 如虎添翼的其他插件

#### IntelliJ IDEA Keybindings

如果你和我一样也是从 Intellij 系列 IDE 迁移过来，想必你也遇到快捷键不习惯的问题。推荐你安装IntelliJ IDEA Keybindings 插件。来映射快捷键，让你在 vscode 可以使用使用 Intellij 的快捷键。
如：

- `alt` + `F7` 查看方法引用
- `ctrl` + `shift` + `↑` 或者 `ctrl` + `shift` + `↓` 移动行
- `cmd` + `F4` 关闭当前窗口
- `alt` + `cmd`+ `→` 或者 `alt` + `cmd`+ `←` 切换到前/后一次操作的鼠标位置了

更多的快捷键映射，可以查看该插件主页。

#### Code Runner

Code Runner 插件，让你可以快速你运行各种语言的代码片段。

在可运行的 go 文件页面，点击界面右上角的`➤` 即可快速运行该文件。

### 概括

通过本篇文章可以看出，依赖于vscode 强大的插件我们可以快速搭建完善的 Go 语言开发环境。而它相较于 IDE 的最大优势则是性能良好、扩展性强、免费和轻量级。

## 开发Go项目最简单的方式 — 一个基于Docker的go 工具

发表于 2016-10-17 更新于 2026-08-04

当我尝试开发一个在 IronWorkerr 上运行的非常简单的程序的时候，我发现目前为止没有一个工具可以让人在几分钟之内运行一段 Go 的示例代码。但在其他语言里面这是可以很容易做到的， 因为他们不像 Go 一样需要设置 GOPATH环境变量，遵守一个特定的代码目录结构，而且他们通常还有更简单的依赖管理工具。

### 有什么更好的方式吗？

我最近想了很多，也写了很过关于 Docker 的文章， 并尝试在所有能使用 Docker 的情境下都坚持使用 Docker（是的，我是 Docker 的超级粉丝）。大部分原因是因为在 Iron.io ，我们从事 Docker 的相关工作。我们运行了很多 Docker 容器，真的很多。在这期间，我已经意识到 Docker 的强大与疯狂之处。相信我，这不只是炒作。

我们向用户展示如何使用 Docker 容器构建和测试他们的 Go 语言程序已经有一段时间了，但始终有一个痛点，让我们如鲠在喉。那便是用户需要将代码放到特定的目录， 配置 GOPATH 环境变量，使用一个第三方工具如 godep 来 加载和代理依赖（注意通常这些依赖和你的代码一样，也需要被版本控制管理），有序的加载相关目录等等。这些当然可以完成，但是总是让人觉得不够爽。

现在，这个流程变得更好些了。

### 介绍下这个基于 Docker 的 Go 工具

我创建了一个基于 Docker 的 go 工具—— “treeder/go” ，他让 Go 语言开发变得超级简单。 你唯一需要安装的只有 Docker。 下面是一些它的一些功能和好处：

- 你不需要安装 Go
- 你不需要安装这些相关的工具
- 你不需要配置 GOPATH 环境变量
- 你不需要将你的代码放到特定的目录（如： /src/github.com/user/hello）或者 Go 的安装目录， 你可以任意放置你的代码。
- 不需要重写代码里面依赖导入目录就可以加载相应依赖
- 代码交叉编译
- 代码静态编译
- 将代码打包成 Docker 镜像（一个命令即可搞定，然后你将得到一个包含你的代码的镜像）
- 构建远端 git 仓库的代码

### 演示

##### 基础部分

让我们先来写个简单的例子，首先复制粘贴下面的代码到一个叫 app.go 的文件，放到任意目录。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    package main

    import (
      "fmt"
      "log"
      "net/http"

      "github.com/gorilla/mux"
    )

    func main() {
      r := mux.NewRouter()
      r.HandleFunc("/", Hello)
      http.Handle("/", r)
      fmt.Println("Starting up on 8080")
      log.Fatal(http.ListenAndServe(":8080", nil))
    }

    func Hello(w http.ResponseWriter, req *http.Request) {
      fmt.Fprintln(w, "Hello world!")
    }

注意到这段代码有第三方依赖了吗？ 让我们来代理（vendor） 依赖：

    1

    docker run --rm -v $PWD:/app -w /app treeder/go vendor

上述命令会把抵赖都放 /vendor 目录下
然后我们对代码进行构建：

    1

    docker run --rm -v $PWD:/app -w /app treeder/go build

接着，我们来运行代码：

    1

    docker run --rm -v $PWD:/app -w /app -p 8080:8080 iron/base ./app

打开浏览器，输入 http://localhost:8080. 哈哈，我们成功的通过 `iron/base` 这个基础镜像运行了我们的代码。它是一个包含了运行 GO 程序所需的所有东西的很小的镜像。

#####更酷炫的东西

构建一个包含你的代码的可以运行的 Docker 镜像怎么样？

    1

    docker run --rm -v $PWD:/app -w /app -v /var/run/docker.sock:/var/run/docker.sock treeder/go image username/myapp:latest

现在通过你的新镜像来运行代码吧：

    1

    docker run --rm -p 8080:8080 username/myapp

再次打开 http://localhost:8080，哈哈，现在流程是不是更好了。 这个镜像非常小。你可以通过输入 `docker images` 来查看这个镜像到底有好大，大概在12M左右吧。

或者你也可以下载和构建一个远程的代码仓库：

    1

    docker run --rm -v $PWD:/app -w /app treeder/go remote https://github.com/treeder/hello-app.go.git

最后你将得到一个包含这个远程代码仓库的代码的镜像。

###结论

将 Docker 运用于开发再次胜利了，如果你之前开发过 Go 项目，你应该会感谢这个工具带来的简单和简洁。不过它还仅仅是个实验阶段的工具，没有包含太多的其他工具链。不过，就我知道的而言，这应该是最简单的 Go 上手方式了。通过这个工具，仅仅告诉其他人一个代码仓库链接，他们就可以克隆，构建，运行代码而不需要任何初始化流程仅仅只需要 Docker。

完整的文档和项目源代码请浏览： https://github.com/treeder/go

请不要吝啬你的任何反馈，创建一个 Github issue 或者评论吧。

`更新: 我做了一个更大更好的工具：https://github.com/treeder/devo`

翻译自：https://medium.com/iron-io-blog/the-easiest-way-to-develop-with-go-introducing-a-docker-based-go-tool-c456238507d6

## 在Rails中使用 active_model_serializers 构建json response

发表于 2015-03-21 更新于 2026-08-04

Rails 本身提供很不错的json response功能，可以很方便的将model对象自动转换为json数据。如果我们期望返回的结果很简单也可以构建一个简单的hash,自行编辑你希望的key和value,由Rails 来帮你生成json。那如果是介于两者之间的情况呢？

- 我希望将我的model以json的形式返回，但是我并不希望将所有的字段返回。
- 我希望将我的model中部分属性进行稍微的处理和计算后返回，这样客户端可以直接使用某些字段，而不需要将应用自身的逻辑暴露给客户端，如我有个model记录微信支付属性，有个字段是关于微信支付（”trade_status”），它的值有trade_success, “wait_for_payment”，显然我们可以返回给客户端 “支付成功”，”等待支付”更好。传统的做法，我们为了达到这个目的，我们不仅需要将trade_stauts进行构建，还需要将其他参数也重复写出来。

ActiveModel::Serializers这个gem 包就可以更好的帮助我们解决上面的痛点，我们只需要对需要返回的属性列举出来，只对需要更改的属性进行计算，其他都不需要了。下面就介绍下它的一些常见用法。

首先安装Gem

    1

    gem 'active_model_serializers'

为了可以在我们的rails 项目中使用它，我们还需要在application controller中添加：

    1

    include ActionController::Serialization

active_model_serializers的使用就是在你是需要返回json的地方，为你的数据创建serializer,你的对象就能通过serializer变成希望的结果。这里假设我有一个User用户对象，User的的大致结构：

    1
    2
    3
    4
    5
    6
    7

    class User
      field :nick_name, type: String
      field :email, type: String
      field :age, type: Integer
      field :password, type:String
      # 等等更多属性。。。
    end

我现在有个UserController,需要以JSON的形式返回用户的基本信息： 昵称，邮箱，是否成年（大于等于18岁算成年），接下来在app 目录下创建serializers 目录，并创建class UserSerializer对象，继承自 ActiveModel::Serializer, 然后我们的serializer就应该是这样：

    1
    2
    3
    4
    5
    6
    7

    class UserSerializer ActiveModel::Serializer
      attributes :nick_name, :email, :if_adult

      def if_adult
        object.age > 18 #object 就是需要被序列化的对象
      end
    end

在serializer中，我们只需要将我们需要的属性通过attributes 的形式列出来，如果model没有的属性，我们需要自行实现该方法。
我们也可以覆盖属性，如上的例子，我们也可以将if_adult 改成age,同样我们需要有：

    1
    2
    3

    def age
      object.age > 18
    end

接下来完成我们的最后一步，在controller中使用serializer

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    class UserController ApplicationController
      def show
        #假设 @user 是我们经过查询后得到的对象
        render json: @user, serializer: UserSerializer
      end

      def index
        #假设 @users 是我们经过查询后得到的对象
        render json: @user, each_serializer: UserSerializer
      end
    end

我们我们希望对一个数组对象进行序列化，我们则需要使用each_serializer，使用该属性后，你的返回结果将变成对象，数组则包裹下对象之下。本例则类似于

    1
    2
    3
    4

    users: [
      {},
      {}
    ]

这里的”users”这是json的根属性， serializer支持用户自定义根属性，

    1

    render json: @user, serializer: UserSerializer, root: 'customer'

我非常喜欢active model serializers 的一个属性是，支持在serializer中访问你希望的属性，在rails 中，很多时候我们希望访问current_user对象，获取当前登录用户的相关信息。那serializer 则可以很好的做的这一点，在active model serializers 中有 serialization_scope 这样一个方法，在application controller 中声明此方法，传入你希望的参数，便可以在serializer class 中自由访问该对象。解决了serializer 与其他对象交互的问题。

    1

    serialization_scope :current_user

在serializer中, scope 对象便是注入的 current_user对象

    1

    scope.email

此外，active model serializers 支持在返回的json中额外注入meta属性，这样既保留了serializer的简单，模板化，也增添了自由度，使得用户可以自行添加一些额外的属性。

更详细的使用还请参考：Github

## 稻城、亚丁自驾游之行的一些照片

发表于 2014-10-25 更新于 2026-08-04

上周星期天，我和她开启了我们一周的稻城亚丁自驾游之旅，虽然途中经历过长达5，6个小时大堵车，因二郎山修路弄得烂泥一样的路面，下雪等诸多不太好的情况，但是我们在途中所看到的景美翻了，呼吸到的空气不能再清新，不得不说稻城、亚丁让我们醉了。总得来说非常值得一去，相比九寨沟最美的是水，亚丁则最美的是蓝天、白云、黄叶、雪山。
此行我们大致的行程是：

    1
    2
    3
    4
    5
    6

    第一天：成都——新都桥（二郎山烂路，因修路堵车5个小时左右）
    第二天：新都桥——稻城 （因318国道修路，有30公里土石路）
    第三天：稻城——亚丁  （仅100公里，可先在亚丁景区附近或者景区内游玩，或游览俄初山，仅30公里左右）
    第四天：亚丁旅游，晚上返回稻城
    第五天：稻城——康定
    第六天：康定——成都（绕道石棉县，上雅西高速回成都）

最后附上我拍的照片几张。

## 5，6月在北京的几张照片

发表于 2014-10-03 更新于 2026-08-04

## 使用七牛云提升博客加载速度

发表于 2014-08-31 更新于 2026-08-04

由于大家都懂的原因，谷歌被彻底封锁了，连供程序员使用的在线托管的第三方库google apis，和 google web fonts 也不能使用了。
这使得本来放在国外的博客变得更慢，关键是如果用了那些库的话，基本上是几分钟都加载不了的节奏。
我的博客放在github page上，最近也发现访问也越来越慢，比如JS、css、图片等加载都很慢。然后就有了优化的想法，恰好之前有同事提到他使用过七牛云还不错，速度在国内挺快，而且注册后还有免费的套餐用，而且基本够用。
现在使用了之后发现，的确够用，对于我这样一个每天只有几十个人访问的博客而言。简单讲讲我是怎么优化的。

- 去掉不必要的JS、CSS等资源文件，我现在使用的是Hexo，最终的博客都是以预生成的静态HTML文件。在详细观察HTML的结构后发现其实有一些js是不需要的，
  如fancybox-一款图片插件插件，提供画廊的形式查看当然博客的图片，对我而言嵌在网页里足以；mathx?,一款用于在网页上显示数学公式的js插件，对我是在没必要。
- 在Chrome 的控制台中发现网页加载图片、和JS奇慢，很多都需要2，3秒才能加载成功。因此我想到了那那些稍大的图片和JS均放到七牛云里面。
- 替换引用的google 相关资源文件，我的博客里面主要用来google web font的一款字体，因为google 上的字体本身也是开源的，我便把我需要使用的字体存一份在七牛云上，
  自己在CSS 里面声明一个@fontface即可。（这样做应该没有侵犯版权吧）
- 使用GZIP 对生成的HTML进行压缩，也可以减小传输时间。

在进行了以上的步骤之后，网页的记载速度有很大提升。之前是ping 通网页以后，通常还需要10秒以上的时间才能及在完，现在大概只需要3秒左右的时间。
偶尔依然比较慢，经过查看后发现依然是剩下放在在github 的js,css加载很慢。Anyway, 已经是可以接受的范围了。

这里不得不赞一下七牛云，在国内的访问速度的确是很话说，因为也曾用过360的一个公共CDN的JS库，加载速度还是会比七牛云慢一截，关键是现在免费的每月10G流量已经够我使用了。
最后放一张优化后的加载时间图.

## 发布iPhone应用到Apple Store的经历

发表于 2014-06-21 更新于 2026-08-04

理想是丰满的，现实是骨干的。
成功在于高效强有力的执行力。

在尝试发布iPhone应用之前就在网上看过一些资料，也在论坛里面看到其他人发的帖子，都提及发布应用时间比较漫长，可能会被苹果打回进行相关修改后才能继续发布。但是没有想到我的这次发布，期间总共进行了大大小小的4次修改，共花了50天左右的时间。下面就聊聊这次发布过程中的故事吧。

— 需要补充 —

0%