如何写高大上的 godoc(Go 文档)

做 Go 开发时,我们在开源项目的主页上我们经常可以看到这样的一个徽章:

点击徽章,就可以打开 godoc.org 的网页,网页中给出了这个开源项目所对应的 Go 文档。作为 Go 语言的新手,我一度以为,godoc.org 上面的文档是需要开发者上传并审核的——要不然那些文档咋都显得那么专业呢。

然而当我写自己的轮子时,慢慢的我就发现并非如此。划重点:在 godoc.org 上的文档,都是 Go 自动从开源项目的工程代码中搜集、格式化后展现出来的。换句话说,每个人都可以写自己的 godoc 并且展示在 godoc.org 上,只需要遵从 godoc 的格式标准即可,也不需要任何审核动作。

本文章的目的是通过例子,简要说明 godoc 的格式,让读者也可以自己写一段高大上的 godoc。以下内容以我自己的 jsonvalue 仓库为例子。其对应的 godoc 在这里。读者可以点开,并与代码中的内容做参考对比。

本文地址:https://cloud.tencent.com/developer/article/1526609

什么是 godoc

顾名思义,godoc 就是 Go 语言的文档。在实际应用中,godoc 可能可以指以下含义:

  1. https://godoc.org 中的内容
  2. Go 开发工具安装之后,自带的一个命令,就叫做 godoc
  3. Go 工具包的文档以及生成该文档所相关的格式

我们从 Go 自带的 godoc 工具讲起吧。前面我们说到的 godoc.org,是 Go 最为官方的文档网站。其中我们可以查阅 Go 原生 package 的文档说明。而 godoc 命令的作用,则是可以让我们在本地建立一个属于自己的 godoc 网站服务(官方的 godoc 其实也基本上是用同一个工具建立起来的)。

自建的 godoc 有两个作用,一是解决某局域网内无法访问 godoc.org 的尴尬,另一个则是可以本地调试自己的文档。

我们可以用下面的命令在本地启动自己的 godoc 服务:

godoc -http=127.0.0.1:6060 -play

或者简写为:

godoc -http=:6060 -play

在浏览器输入 http://127.0.0.1:6060 之后,就可以看到熟悉的 Go 文档页面了:

原理上,godoc 读取的包路径来自于 $GOROOT。因此,如果你要让本地的 godoc 认识并解析你自己的开发包,就应该在 $GOROOT 目录下按照路径结构放好自己的工程代码——软链接也是支持的。比如笔者的 jsonvalue 包,我放在了这个路径下:~/project/github.com/Andrew-M-C/go.jsonvalue,于是我就在 $GOROOT 下建了软链接:

$ go env | grep GOROOT | sed 's/GOROOT=//g' | xargs cd
$ ln -s ~/project/github.com ./

然后在浏览器中输入 http://127.0.0.1:6060/pkg/github.com/Andrew-M-C/go.jsonvalue/,就可以看到和 godoc.org 一样的页面了。

godoc 一览

Go 秉承 “注释即文档” 的理念,符合 godoc 的文档均从 Go 代码中提取并生成。我们还是从 jsonvalue 的 godoc 来看,一个一个说明。在 godoc 中,文档包含三大部分:

 组成

 作用

Overview 总览

包含包的 import 语句和概要说明

Index 目录

包含包中可见性为 public 的常量、类型、方法、函数的总目录及说明

Examples 示例

包含文档中所有示例的快速跳转

Files 文件

列出了包中所有代码文件的超链接

其中第四部分无关紧要。下面我们按顺序说明前三部分

godoc 的 Overview

Package jsonvalue 的 Overview 部分包含了三部分内容:

  • import 语句
  • 文字说明
  • 代码部分

其中 import 部分是 godoc 自动按照 URL 生成的,这个不用管。至于文字部分和代码部分,godoc 都是从源码中提取出来的。提取的原则是:

  • 在代码中所有 package jsonvalue 语句中,找到其上方紧跟着的 // jsonvalue XXX 或者是 /* jsonvalue XXX */ 注释块
  • 注释块可以有多行,但必须是连续的 // 或者 /* XXX */ 开头。如果需要换行,则留一行空注释
  • 如果找到多个符合条件的注释,则按照文件字母序显示——建议把 Overview 放在一个注释块中,而不要分散撰写。

比如 jsonvalue 的 Overview 说明,统一放在 doc.go 中,这个文件中只有 package jsonvalue 语句以及包说明——这也是不少文章中推荐的做法。

Overview 的文字部分

请读者打开 doc.go,然后对比 godoc,就可以对照着看到文字部分是怎么被 godoc 呈现出来的。

Overview 的代码部分

在注释中,如果在 // 后面的注释文本中,如果以 tab 进行了锁进,那么 godoc 会将这一行视为代码块。比如下面这一段:

其中 "As a quick start:" 行的左边分别为:两个斜杠 + 一个空格。这一行,godoc 视为普通文字;而其余部分的左边为:两个斜杠 + 一个空格 + 一个tab,被 godoc 视为代码部分。于是我们在 godoc 网页上,就可以看到这样的显示结果了:

godoc 的代码文档

godoc 工具会搜寻代码中所有源码文件(自测文件除外),然后展示到页面上。搜索的依据如下:

  • 搜寻对象是代码中所有的公共部分,包括常量、变量、接口、类型、函数
  • 与 Overview 类似,紧跟着一个公共元素的、以该元素开头的注释段,会被 godoc 视为该元素的注释
  • 换行逻辑和代码块逻辑的处理也与 Overview 相同

不过在源码说明中,更多的采用代码示例来说明逻辑,因此在这一环节中,代码块比较少用。

这里我用 jsonvalueAt() 函数为例。在代码中,对于 Set() 函数我是这么写的(请无视我蹩脚的英文):

// At completes the following operation of Set(). It defines posttion of value in Set() and return the new value set.
//
// The usage of At() is perhaps the most important. This function will recursivly search for child value, and set the new value specified by Set() or SetXxx() series functions. Please unfold and read the following examples, they are important.
func (s *Set) At(firstParam interface{}, otherParams ...interface{}) (*V, error) {
    ......
}

godoc 解析并格式化效果如下:

godoc 的代码示例

读者可以注意到,在我的 At() 函数下,除了上文提到的文档正文之外,还有五个代码示例。那么,文档中的代码示例又应该如何写呢?

首先,我们应该新建至少一个文件,专门用来存放示例代码。比如我就把示例代码写在了 example_jsonvalue_test.go 文件中。这个文件的 package 名也不得与当前包名相同,而应该命名为 包名_test 的格式。

示例代码的声明

如何声明一个示例代码,这里我举两个例子。首先是在 At() 函数下名为 “Example (1)” 的示例。在代码中,我把这个函数命名为:

func ExampleSet_At_1() {
    ......
}

这个函数命名有几个部分:

 函数名组成部分

  说明

Example

这是示例代码的固有开头

Set

表示这是类型 Set 的示例

第一个下划线 _

分隔符,在这个分隔符后面的,是 Set 类型的成员函数名

At

表示这是函数 At() 的示例,搭配前面的内容,则表示这是类型 Set 的成员函数 At() 的示例

第二个下划线 _

分隔符,在这个分隔符后面的内容,是示例代码的额外说明

1

这是示例代码的额外说明,也就是前面 “Example (1)” 括号里的部分

另外,示例代码中应该包含标准输出内容,这样便于读者了解执行情况。标准输出内容在函数内的最后,采用 // Output: 单独起一行开头,剩下的每一行标准输出写一行注释。

相对应地,如果你想要给(不属于任何一个类型的)函数写示例的话,则去掉上文中关于 “类型” 的字段;如果你不需要示例的额外说明符,则去掉 “额外说明” 字段。比如说,我给类型 Opt 写的示例就只有一个,在代码中,只有一行:

func ExampleOpt() {
    ........
}

甚至连示例说明都没有。

如果一个元素包含多个例子,那么 godoc 会按照字母序对示例及其相应的说明排序。这也就是为什么我干脆在 At() 函数中,示例标为一二三四五的原因,因为这是我希望读者阅读示例的顺序。

在官网上发布 godoc

好了,当你写好了自己的 godoc 之后,总不是自己看自己自娱自乐吧,总归是要发布出来给大家看的。

其实发布也很简单:当你将包含了 godox 的代码 push 之后(比如发布到 github 上),就可以在浏览器中输入 https://godoc/org/${package路径名}。比如 jsonvalue 的 Github 路径(也等同于 import 路径)为 github.com/Andrew-M-C/go.jsonvalue,因此输入 godoc.org/github.com/Andrew-M-C/go.jsonvalue

如果这是该页面第一次进入,那么 godoc.org 会首先获取、解析和更新代码仓库中的文档内容,并且格式化之后展示。在页面的底部,会列出该 godoc 的更新时间。

如果你发现官网上的 godoc 内容已经落后了,那么可以点 “Refresh now” 链接刷新它。

接下来更重要的是,把这份官网 godoc 的链接,附到你自己的 README 中。还是点上图的 “Tools” 链接,就可以在新页面中,看到相应的 godoc 徽标的链接了。有 htmlmarkdown 格式任君选择。


本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

原作者: amc,欢迎转载,但请注明出处。

原文标题:如何写高大上的 godoc(Go 文档)

发布日期:2019/10/24

原文链接:https://cloud.tencent.com/developer/article/1526609

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏林冠宏的技术文章

Golang:线程 和 协程 的区别

国庆越快各位,距离上次发文快两个月了,19年也快结束了。现在的总结更多是放在了草稿 而没有发出,这次详细分享下在 Go 中,线程和协程的区别及其关系。

10130
来自专栏雪之梦技术驿站

go 学习笔记之10 分钟简要理解 go 语言闭包技术

闭包是主流编程语言中的一种通用技术,常常和函数式编程进行强强联合,本文主要是介绍 Go 语言中什么是闭包以及怎么理解闭包.

2410
来自专栏雪之梦技术驿站

go 学习笔记之仅仅需要一个示例就能讲清楚什么闭包

本篇文章是 Go 语言学习笔记之函数式编程系列文章的第二篇,上一篇介绍了函数基础,这一篇文章重点介绍函数的重要应用之一: 闭包

2110
来自专栏区块链入门

【实践】GO语言框架REDIGO使用REDIS数据库入门

基于GO的REDIOS调用框架有开源库redigo。本文主要讲解redigo的框架和调用样例。

15530
来自专栏landv

[golang]写了一个可以用 go 来写脚本的工具:gosl

代码和使用说明可以看这里: http://github.com/daviddengcn/gosl

13830
来自专栏小诚信驿站

Go的面试笔试基础考察区别点

#############################分割线###############################################

25710
来自专栏小诚信驿站

Go的代码规范指南-新人必看

环境设置:*nix环境或者Mac环境,安装go语言目录,默认是usr/local/go,如果想要让代码运行,需要将项目放到usr/local/go/src目录下...

30740
来自专栏贺利权

咦,Android Studio 3.5 Retry ?

总会有那么一个人,让你觉得这个世界一切都是值得的。纵使结果不尽人意,曾经拥有即是最好。

7130
来自专栏AI研习社

官宣!TensorFlow 2.0 正式发布

今年初,我们在 TensorFlow 开发者大会 (TensorFlow Dev Summit) 上发布了 TensorFlow 2.0 的 Alpha 版本。...

10120
来自专栏苏生不惑

那些我常用的 Chrome 扩展(二)

这是一个微博备份的扩展,由于没有上架,只能下载到本地安装,下载地址 https://share.weiyun.com/56v1cyU,具体使用见微博https:...

12530

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励