服务不可用现象
· 7 min read
go doc 是 Go 语言文档工具的深度解析,🉑快速检索和阅读 Go 包、类型、函数的文档注释。
一、基础用法
go doc
go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>
go doc <pkg> <sym>[.<methodOrField>]
go doc text/template.new # One argument
Show documentation for text/template's New function.
go doc text/template new # Two arguments
Show documentation for text/template's New function.
Flags:
-all
Show all the documentation for the package.
-c
Respect case when matching symbols.
-cmd
Treat a command (package main) like a regular package.
Otherwise package main's exported symbols are hidden
when showing the package's top-level documentation.
-short
One-line representation for each symbol.
-src
Show the full source code for the symbol. This will
display the full Go source of its declaration and
definition, such as a function definition (including
the body), type declaration or enclosing const
block. The output may therefore include unexported
details.
-u
Show documentation for unexported as well as exported
symbols, methods, and fields.
查看包文档
go doc fmt # 查看标准库 fmt 包的整体文档
go doc net/http # 查看 net/http 包的文档
go doc github.com/gin-gonic/gin # 查看第三方包文档
查看类型/函数/变量文档
go doc fmt.Printf # 查看函数文档
go doc os.File # 查看类型(结构体/接口)文档
go doc context.CancelFunc # 查看类型别名文档
go doc http.StatusNotFound # 查看常量/变量文档
查看方法文档
go doc strings.Builder.Write # 查看结构体方法
控制精确输出
go doc -all net # 查看 net 包所有的文档
go doc -u runtime._Lock # 查看未导出的内部标识符(谨慎使用)
go doc -c bytes.Buffer.Write # 查看函数被哪些代码调用
二、🎬 快速掌握Go代码库核心功能
接手一个陌生的 Go 项目时,如何快速了解 Go 项目代码阅读技巧,快速来理解项目核心设计。
问题:
大多数开发者习惯的「从上到下线性阅读」的方式阅读代码,很容易带来几个问题:
- 陷入细节沼泽:过早陷入函数实现细节
- 错过整体脉络:只见树木不见森林🌳
- 时间消耗巨大:阅读完整项目需要很长时间。
逆向阅读三部曲:
A[库函数 function] --> B[结构体定义 struct] --> C[结构函数 method]
库函数: 我们可以直观的看到该项目或者包对外提供了哪些功能 结构定义:从结构体定义我们可以直观的看到该包有哪些核心模块,他们大概是负责什么功能 结构函数:了解了各个模块负责的功能,我们就可以看某一个模块的具体实现了
查看库函数:
# 提取包的所有公开函数
go doc <package> | grep "^func"
go doc net/http | grep "^func"
go doc runtime | grep "^func"
查看核心结构体
go doc <package> | grep "^type" | grep struct
追踪结构体方法
# 查看特定结构体的方法集
go doc <package>.<Struct>
go doc net/http.Server
三、🎬 godoc 使用
godoc 提供更强大的 web 界面文档服务:
godoc -http=:6060
open http://localhost:6060
推荐使用 go doc xxx
。
四、查询本地项目
递归查询当前目录下的所有结构
方法 1:结合 find
命令递归查看所有子包
可以使用 find
命令递归查找所有 Go 包目录,并对每个包运行 go doc
。
find . -type d -exec go doc {} \;
解释:
find . -type d
:递归查找当前目录下的所有子目录。-exec go doc {}
:对每个子目录执行go doc
。go doc
会在每个目录中查找main
包或与该目录对应的 Go 包并显示该包的文档。
优化: 只对包含 Go 文件的目录运行 go doc
find . -type f -name '*.go' -exec dirname {} \; | sort -u | xargs -I {} go doc {} | grep "^type" | grep struct
解释:
find . -type f -name '*.go'
:查找所有 Go 文件。dirname {}
:获取包含这些 Go 文件的目录。sort -u
:去重,避免重复处理同一个目录。xargs -I {}
:针对每个目录运行go doc
。
方法 2:使用 go list
获取所有子包并查看文档
go list
可以列出当前项目的所有 Go 包,结合 go doc
可以递归查看子包的函数定义。
1、在项目根目录运行以下命令:
go list ./... | xargs -I {} go doc {}
解释:
go list ./...
:递归列出当前模块及其所有子包的包路径。xargs -I {}
:针对每个包路径运行go doc
。
2、如果需要显示更详细的输出(包括函数定义),可以使用 go doc -all
:
go list ./... | xargs -I {} go doc -all {}
-all
参数:
- 显示包的所有文档,包括包注释、常量、变量、函数、类型及其方法。
五、一个例子🌰
查看 runtime 包下的对外函数
go doc runtime | grep "^func"
func BlockProfile(p []BlockProfileRecord) (n int, ok bool)
func Breakpoint()
func CPUProfile() []byte
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
func Callers(skip int, pc []uintptr) int
func GC()
func GOMAXPROCS(n int) int
func GOROOT() string
func Goexit()
func GoroutineProfile(p []StackRecord) (n int, ok bool)
func Gosched()
func KeepAlive(x any)
func LockOSThread()
func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool)
func MutexProfile(p []BlockProfileRecord) (n int, ok bool)
func NumCPU() int
func NumCgoCall() int64
func NumGoroutine() int
func ReadMemStats(m *MemStats)
func ReadTrace() []byte
func SetBlockProfileRate(rate int)
func SetCPUProfileRate(hz int)
func SetCgoTraceback(version int, traceback, context, symbolizer unsafe.Pointer)
func SetFinalizer(obj any, finalizer any)
func SetMutexProfileFraction(rate int) int
func Stack(buf []byte, all bool) int
func StartTrace() error
func StopTrace()
func ThreadCreateProfile(p []StackRecord) (n int, ok bool)
func UnlockOSThread()
func Version() string
查看具体函数定义
go doc runtime.ReadMemStats
package runtime // import "runtime"
func ReadMemStats(m *MemStats)
ReadMemStats populates m with memory allocator statistics.
The returned memory allocator statistics are up to date as of the call to
ReadMemStats. This is in contrast with a heap profile, which is a snapshot
as of the most recently completed garbage collection cycle.
go doc runtime.KeepAlive
package runtime // import "runtime"
func KeepAlive(x any)
KeepAlive marks its argument as currently reachable. This ensures that the
object is not freed, and its finalizer is not run, before the point in the
program where KeepAlive is called.
A very simplified example showing where KeepAlive is required:
type File struct { d int }
d, err := syscall.Open("/file/path", syscall.O_RDONLY, 0)
// ... do something if err != nil ...
p := &File{d}
runtime.SetFinalizer(p, func(p *File) { syscall.Close(p.d) })
var buf [10]byte
n, err := syscall.Read(p.d, buf[:])
// Ensure p is not finalized until Read returns.
runtime.KeepAlive(p)
// No more uses of p after this point.
Without the KeepAlive call, the finalizer could run at the start of
syscall.Read, closing the file descriptor before syscall.Read makes the
actual system call.
Note: KeepAlive should only be used to prevent finalizers from running
prematurely. In particular, when used with unsafe.Pointer, the rules for
valid uses of unsafe.Pointer still apply.
六、小结:
多使用 go doc
查看项目结构。