1

When we first started Go development, we often saw a badge like this on the homepage of an open source project:

image.png

Click the badge to open the https://pkg.go.dev/ webpage, which gives the Go document corresponding to this open source project. When I first came into contact with Go, I once thought that the documents on pkg.go.dev need to be uploaded and reviewed by developers - otherwise, why do those documents look so professional.

However, as I wrote my own wheels, I slowly discovered that this was not the case. focuses on : The documents on pkg.go.dev are all automatically crawled and formatted by Go from the engineering code of open source projects. In other words, everyone can write their own GoDoc and display it on pkg.go.dev , just follow the GoDoc format standard, and do not need any auditing action.

The purpose of this article is to briefly explain the format of GoDoc by example, so that readers can also write a tall godoc by themselves. The following uses my own jsonvalue package as an example. Its corresponding GoDoc is here . Readers can click on it and compare it with the content in the code.

What is GoDoc

As the name suggests, GoDoc is the documentation of the Go language. In practical applications, godoc may refer to the following meanings:

  1. Before 2019.11, means the content in https://godoc.org
  2. Now that godoc.org has been offline, it will be redirected to pkg.go.dev , and its functions have been re-migrated to this - the following refers to this meaning with " pkg.go.dev "
  3. A command of the Go development tool is called godoc - this tool is directly referred to as " godoc " below
  4. The related command of pkg.go.dev is called pkgsite , and the code is hosted on GitHub - hereafter " pkgsite " refers to this tool
  5. Documentation for the Go toolkit and the format associated with generating it - hereafter referred to as " GoDoc "

The current godoc and pkgsite have two functions, one is to debug your own GoDoc display locally; the other is to build a GoDoc server locally when you cannot access the Internet scientifically.

godoc command

Let's start with the tool command. Before 2019, Go used the godoc tool to format and display documentation that comes with Go code. Now this command is no longer included in the Go toolchain and requires additional installation:

go get -v golang.org/x/tools/cmd/godoc

The godoc command has various modes and parameters, here we list the most common and easiest modes:

cd XXXX; godoc -http=:6060

where XXXX is a repository directory containing go.mod. Assuming XXX is the local directory of my jsonvalue library, according to go.mod, the address of this library is github.com/Andrew-M-C/go.jsonvalue , then I can open http://${IP}:${PORT}/pkg/github.com/Andrew-M-C/go.jsonvalue/ in the browser, and then I can access the GoDoc page of my jsonvalue library, as shown in the following figure shown:

image.png

pkgsite command

As mentioned above, pkg.go.dev is now officially maintained and used by Go, so this article mainly describes the usage of pkgsite .

The current pkgsite requires Go version 1.18, so please upgrade the Go version to 1.18 . Then we need to install pkgsite :

go install golang.org/x/pkgsite/cmd/pkgsite@latest

Then similar to godoc:

cd XXXX; pkgsite -http=:6060

jsonvalue as an example. The browser's address is similar to godoc, but pkg/ : http://${IP}:${PORT}/github.com/Andrew-M-C/go.jsonvalue/ is missing, and the page is as shown below:

image.png

pkg.go.dev contents

Overall content

Since I have played a lot with GoDoc in jsonvalue , I still use this library as an example. We open the home page of the relevant package in pkg.go.dev , and we can see these contents:

image.png

  • A - the full path to the current package
  • B - the name of the current package, where module indicates that this is a package that conforms to the go module
  • C - Some basic information of the current package, including the latest version, release time, certificate, the number of dependent packages (including system packages), and the number of referenced packages
  • D - If the current package contains a README file, display the contents of the README file
  • E - the content of the comment as document document in the current package
  • F - The file list of the current package, you can click to quickly browse
  • G - list of subdirectories of the current package

If your README (markdown format) has subtitles, then pkgsite will generate a secondary directory index under the README. The format of Markdown is not explained in this article, I believe that code farmers are familiar with it.

Documentation

Let's click on Documentation, a complete package that may contain the following:

image.png

subsectionillustrate
OverviewThis is an overview of the entire package, taking the "package comments" part of the go code
IndexThis is the general directory of the entire GoDoc content, including all exportable functions, methods, constants, variables and example code
VariablesAll exportable variables are listed here. In fact, a well-packaged package should be empty after clicking here
FunctionsAll exportable functions (except functions returning exportable types)
TypesAll exportable types and their methods, as well as a list of exportable functions that can generate corresponding types (such as various constructors)

In fact, the content of Documentation is GoDoc. Go adheres to the concept of "annotation is a document", among which pkg.go.dev , godoc and pkgsite all use the same set of GoDoc format, and all three extract from the comments of the document according to this format, and generate the document.

Let's take a look at the syntax of GoDoc in detail.

GoDoc syntax

In GoDoc, all exportable types of the current package will be displayed on the pkg.go.dev page. Even if an exportable type does not have any comments, GoDoc will also display the prototype of the exportable content - of course, we should Always remember: All exportable content should be well commented.

GoDoc supports comments in two modes: // and /* ... */ . But I still recommend to use // , which is also the current mainstream of annotations, and most IDEs also support one-click conversion of multi-line text into comments (such as VsCode for Mac, use command + / ). Although /* */ is very convenient in multi-line comments, once I see this, it always feels like code from ancient times (dog head).

Bind GoDoc with the specified type

For any exportable content, the comment immediately above the code definition will be regarded as the GoDoc of the content and thus extracted. For example:

// 这一行,会被视为 SomeTypeA 的 GoDoc,
// 因为它紧挨着 SomeTypeA 的定义。
type SomeTypeA struct{}

// 这一行与 SomeTypeB 的定义之间隔了一行,
// 所以并不会认为是 SomeTypeB 的 GoDoc。

type SomeTypeB struct{}

/*
使用这种注释符的注释也是同理,因为整个注释块紧挨着 SomeTypeC 的定义,
因此会被视为 SomeTypeC 的注释。
*/
type SomeTypeC struct{}

The display effect of these three types on the pkgsite page is as follows:

image.png

However, please note that according to the official recommendation of Go, the first word of a code comment should be the commented content itself. For example, in the previous article, the comment of SomeTypeA should start with // SomeTypeA . This specification will be used uniformly from the beginning.

line break (paragraph)

Readers can notice that I have changed a line for all valid comments in the preceding text; however, in the page display of pkgsite , line breaks did not occur.

In fact, if the comment is simply a new line and another comment, the page will not treat it as a new paragraph of . GoDoc's logic is only after rendering this line, add a space and then continue rendering the next line.

If we want to add a new paragraph in the same comment block, then we need to insert an empty comment, as follows:

// SomeNewLine 只是用来展示如何在 GoDoc 中换行。
//
// 你看,这就是新的一行了,耶~✌️
func SomeNewLine() error {
    return nil
}

image.png

inline code

If necessary, we can embed a small piece of code in the comment, and the code will be separated into a paragraph and displayed using monospaced characters. Take the following example:

// IntsElem 用于不 panic 地从一个 int 切片中读取元素,并且返回值和实际在切片中的位置。
//
// 不论是任何情况,如果切片长为0,则 actual Index 返回 -1.
//
// 根据参数 index 可以有几种情况:
//
// - 零值,则直接取切片的第一个值
//
// - 正值,则从切片0位置开始,如果遇到切片结束了,那么就循环从头开始数
//
// - 负值,则表示逆序,此时则循环从切片的最后一个值开始数
//
// 负值的例子:
//
//    sli := []int{0, -1, -2, -3}
//    val, idx := IntsElem(sli, -2)
//
// 返回得 val = -2, idx = 2
func IntsElem(ints []int, index int) (value, actualIndex int) {
    // ......
}

image.png

To summarize: In a comment block, a part of a commented line is considered a code block if it meets one of the following criteria:

  • Comment lines start with tab \t
  • Comment line starts with more than one space (including tab)

There is no need to use special empty comment lines between ordinary comments and code blocks, but it is better to add them as personal suggestions.

Overview section

In the Overview part of the Documentation, is the description of the entire package, this type of comments, known as "package comments." Package comments are written at the beginning of the go file at package xxx . Although GoDoc has no restrictions, Go officially recommends that package comments should start with // Package xxx as the subject of the text.

If multiple files in a package contain package comments, GoDoc will display the package comments in these files in turn according to the lexicographical order of the files. But this may lead to confusion, so a package we should write package

In general, we can choose the following files to write package comments:

  • There will be a xxx.go file with the same name as the package name under many packages, then we can write package comments in this file uniformly, such as and ;
  • If the xxx.go file itself carries a lot of code, or the package comments are relatively long, then we can open a doc.go file to write package comments, such as like .

Deprecated code declaration

The version number used by Go is the mode of vX.Y.Z . According to the official idea, whenever the package is upgraded, try not to upgrade the X value of the large version, which also means that this upgrade is completely forward compatible. But in fact, when we do some minor or medium version upgrades, some functions/types may no longer be recommended. At this point, GoDoc provides a keyword Deprecated: as the first word of the entire comment block. For example, we can write:

// Deprecated: ElemAt 这个函数弃用,后续请迁移到 IntsElem 函数中.
func ElemAt(ints []int, index int) int {
    // ......
}

For deprecated content, pkgsite will be identified in the directory on the one hand:

image.png

In addition, in the text, it is also deliberately displayed in gray fonts in a low-key manner, and the text of the note is hidden, which needs to be clicked to display:

image.png

image.png

code sample documentation

If readers look at the document of my jsonvalue, under the At() function, in addition to the document body mentioned above, there are five code examples:

image.png

So, how should the code examples in the documentation be written?

First, we should create at least one file dedicated to the sample code. For example, I wrote the sample code in the example_jsonvalue_test.go file. The package name of this file should not be the as the current package name, but should be named in the format of package name _test.

In addition, it should be noted that the sample code file also belongs to the content of the unit test file. When go test is executed, the sample file will also be included in the test logic.

Declaration of sample code

How to declare a sample code, here I give two examples. The first is an example named "Example (1)" under the At() function. In code I named this function:

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

This function name has several parts:

Function name component Description
ExampleThis is the inherent beginning of the sample code
Setmeans this is an example of type Set
The first underscore _The separator, after this separator, is the member function name of type Set
AtIndicates that this is an example of the function At() , and with the previous content, it indicates that this is an example of the member function At() of type Set
The second underscore _Delimiter, the content after this delimiter is an additional description of the sample code
1This is an additional explanation of the example code, which is the part in the parentheses of "Example (1)"

Also, the standard output should be included in the sample code so that the reader can understand the execution. At the end of the standard output content in the function, use // Output: to start a line alone, and write a comment for each remaining line of standard output.

Correspondingly, if you want to write an example for a function (that does not belong to any type), then remove the "type" field above; if you don't need the extra specifier of the example, remove the "extra specification" field . For example, the example I wrote for type Opt has only one, and in the code , there is only one line:

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

Not even an example description.

If an element contains multiple examples, godoc the examples and their corresponding descriptions alphabetically. That's why I simply marked the examples as one two three four five in the At() function, because that's the order I want the reader to read the examples.

Publish GoDoc on the official website

Well, after you have written your own GoDoc, it's not just to entertain yourself, but to publish it for everyone to see.

In fact, publishing is also very simple: when you push the code that contains godox (such as publishing it to github), you can enter https://pkg.go.dev/${package path name} in the browser. For example, the Github path (also equivalent to the import path) of jsonvalue is github.com/Andrew-M-C/go.jsonvalue , so enter https://pkg.go.dev/github.com/Andrew-M-C/go.jsonvalue .

If this is the first time the page is accessed, pkg.go.dev will first obtain, parse and update the document content in the code repository, format it and display it. In pkg.go.dev , the GoDoc on the tag (instead of the trunk branch) is listed if the latest tag version of the package can be found.

More importantly, attach the link to the official website GoDoc to your own README. We can enter pkg.go.dev badge generate page

Enter the warehouse address to see the link to the corresponding logo. There are html and markdown formats for you to choose.

image.png

References


This article is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License .

This article was first published on Cloud + Community , and it is also the blog of himself .

Original author: amc , welcome to reprint, but please follow the above agreement and indicate the source.

Original title: As a Gopher, do you know how Go's comments or documents should be written?

Release date: 2022/03/24

Original link: https://segmentfault.com/a/1190000041604192 .

Another: part of the content of this article is similar to the article " how to write a high-level godoc " previously published by the author, but at that time, it was written and there was no pkg.go.dev . So I rewrote this.

image.png


amc
924 声望224 粉丝

电子和互联网深耕多年,拥有丰富的嵌入式和服务器开发经验。现负责腾讯心悦俱乐部后台开发