20 Organizing Go code 组织go代码
Organizing Go code
16 August 2012
Introduction
Go code is organized differently to that of other languages. This post discusses how to name and package the elements of your Go program to best serve its users.
Choose good names
The names you choose affect how you think about your code, so take care when naming your package and its exported identifiers.
A package's name provides context for its contents. For instance, the bytes package from the standard library exports the Buffer
type. On its own, the name Buffer
isn't very descriptive, but when combined with its package name its meaning becomes clear: bytes.Buffer
. If the package had a less descriptive name, like util
, the buffer would likely acquire the longer and clumsier name util.BytesBuffer
.
Don't be shy about renaming things as you work. As you spend time with your program you will better understand how its pieces fit together and, therefore, what their names should be. There's no need to lock yourself into early decisions. (The gofmt command has a -r
flag that provides a syntax-aware search and replace, making large-scale refactoring easier.)
A good name is the most important part of a software interface: the name is the first thing every client of the code will see. A well-chosen name is therefore the starting point for good documentation. Many of the following practices result organically from good naming.
Choose a good import path (make your package "go get"-able)
An import path is the string with which users import a package. It specifies the directory (relative to $GOROOT/src/pkg
or $GOPATH/src
) in which the package's source code resides.
Import paths should be globally unique, so use the path of your source repository as its base. For instance, the websocket
package from the go.net
sub-repository has an import path of "golang.org/x/net/websocket"
. The Go project owns the path "github.com/golang"
, so that path cannot be used by another author for a different package. Because the repository URL and import path are one and the same, the go get
command can fetch and install the package automatically.
If you don't use a hosted source repository, choose some unique prefix such as a domain, company, or project name. As an example, the import path of all Google's internal Go code starts with the string "google"
.
The last element of the import path is typically the same as the package name. For instance, the import path "net/http"
contains package http
. This is not a requirement - you can make them different if you like - but you should follow the convention for predictability's sake: a user might be surprised that import "foo/bar"
introduces the identifier quux
into the package name space.
Sometimes people set GOPATH
to the root of their source repository and put their packages in directories relative to the repository root, such as "src/my/package"
. On one hand, this keeps the import paths short ("my/package"
instead of "github.com/me/project/my/package"
), but on the other it breaks go get
and forces users to re-set their GOPATH
to use the package. Don't do this.
Minimize the exported interface
Your code is likely composed of many small pieces of useful code, and so it is tempting to expose much of that functionality in your package's exported interface. Resist that urge!
The larger the interface you provide, the more you must support. Users will quickly come to depend on every type, function, variable, and constant you export, creating an implicit contract that you must honor in perpetuity or risk breaking your users' programs. In preparing Go 1 we carefully reviewed the standard library's exported interfaces and removed the parts we weren't ready to commit to. You should take similar care when distributing your own libraries.
If in doubt, leave it out!
What to put into a package
It is easy to just throw everything into a "grab bag" package, but this dilutes the meaning of the package name (as it must encompass a lot of functionality) and forces the users of small parts of the package to compile and link a lot of unrelated code.
On the other hand, it is also easy to go overboard in splitting your code into small packages, in which case you will likely becomes bogged down in interface design, rather than just getting the job done.
Look to the Go standard libraries as a guide. Some of its packages are large and some are small. For instance, the http package comprises 17 go source files (excluding tests) and exports 109 identifiers, and the hash package consists of one file that exports just three declarations. There is no hard and fast rule; both approaches are appropriate given their context.
With that said, package main is often larger than other packages. Complex commands contain a lot of code that is of little use outside the context of the executable, and often it's simpler to just keep it all in the one place. For instance, the go tool is more than 12000 lines spread across 34 files.
Document your code
Good documentation is an essential quality of usable and maintainable code. Read the Godoc: documenting Go code article to learn how to write good doc comments.
By Andrew Gerrand
Related articles
- A Proposal for Package Versioning in Go
- HTTP/2 Server Push
- Introducing HTTP Tracing
- Testable Examples in Go
- Generating code
- The cover story
- Introducing the Go Race Detector
- Go maps in action
- go fmt your code
- The App Engine SDK and workspaces (GOPATH)
- Debugging Go programs with the GNU Debugger
- The Go image/draw package
- The Go image package
- The Laws of Reflection
- Error handling and Go
- "First Class Functions in Go"
- Profiling Go Programs
- Spotlight on external Go libraries
- A GIF decoder: an exercise in Go interfaces
- Introducing Gofix
- Godoc: documenting Go code
- Gobs of data
- C? Go? Cgo!
- JSON and Go
- Go Slices: usage and internals
- Go Concurrency Patterns: Timing out, moving on
- Defer, Panic, and Recover
- Share Memory By Communicating
- JSON-RPC: a tale of interfaces
20 Organizing Go code 组织go代码的更多相关文章
- 组织Golang代码
本月初golang官方blog(需要自己搭梯子)上发布了一篇文章,简要介绍了近几个月Go在一 些技术会议上(比如Google I/O.Gopher SummerFest等)的主题分享并伴有slide链 ...
- ECLIPSE使用HG插件去上载 GOOGLE.CODE下的代码
ECLIPSE使用HG插件去上载 GOOGLE.CODE下的代码 www.MyException.Cn 发布于:2012-09-10 22:20:12 浏览:112次 0 ECLIPSE使 ...
- 重读 code complete 说说代码质量
重读code complete 说说代码质量 2014年的第一篇文章本来计划写些过去一年的总结和新年展望,但是因为还有一些事情要过一阵才能完成,所以姑且不谈这个,说说最近重读code complete ...
- C# ORM—Entity Framework 之Code first(代码优先)(二)
一.Entity Framework Code first(代码优先)使用过程 1.1Entity Framework 代码优先简介 不得不提Entity Framework Code First这个 ...
- Sublime Text3—Code Snippets(自定义代码片段)
摘要 程序员总是会不断的重复写一些简单的代码片段,为了提高编码效率,我们可以把经常用到的代码保存起来再调用. 平时用sublime安装各种插件,使用Tab键快速补全,便是snippets(可译为代码片 ...
- 使用visual studio code调试php代码
这回使用visual studio code折腾php代码的调试,又是一顿折腾,无论如何都进不了断点.好在就要放弃使用visual studio code工具的时候,折腾好了,汗~ 这里把步骤记录下来 ...
- #001 如何组织JS代码
如何组织JS代码 有没有这样的经历,在编写代码的时候,因为功能简单,写的时候比较随意,所有的JS代码都放在一个文件里面,但是随着功能的增加,发现代码很乱,不好维护. 简单的整理了一下,目前对已有项目的 ...
- eclipse 编辑器支持 Code Minings(代码挖掘)功能
Java 编辑器支持 Code Minings 功能 Java 编辑器现在可以在 Java 元素的上方以“装饰文本”的形式显示实现和引用的数量,即 Code Minings(代码挖掘)功能 启用路径: ...
- Dynamic Code Evaluation:Code Injection 动态代码评估:代码注入
随机推荐
- Mybatis笔记三:MyBatis的API文档
mybatis文档:http://www.mybatis.org/mybatis-3/zh/getting-started.html mybatis-spring文档:http://www.mybat ...
- 解题:HDU 4609 Three Idiots
题面 要求组合的方法显然我们需要对桶卷积,即设$F(x)=\sum\limits_{i=1}^{maxx}x^{cnt[i]}$,然后我们初步的先把$F^2(x)$卷出来,表示选两条边.然后我们发现如 ...
- 解题:POI 2007 Driving Exam
题面 有点意思的题 从一个位置$i$出发可以到达每一个位置即是从$1,n$出发可以到达$i$.然后有了一个做法:把图上下反转后建反图,这样就可以求从一个点$i$到达左右两侧的花费$dp[i][0/1] ...
- bzoj 4451 : [Cerc2015]Frightful Formula FFT
4451: [Cerc2015]Frightful Formula Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 177 Solved: 57[Sub ...
- 【纪中集训2019.3.23】IOer
题目 描述 你要在\(m\)天内,刷\(n\)道题,每天可以刷的题的数目不限: 第\(i\)天可以刷的题目的种类是\(ui+v\): 两种刷题的方案不同当且仅当某天刷题的数量不同或者依次刷题的种类不同 ...
- 【DP】【CF1099C】 Postcard
Description 给定一个长度为 \(n\) 的字符串,尽可能包含小写字母,字符 '?' 和字符 '*'.保证上面两种特殊字符若出现则一定出现在一个小写字母的后面一位.要求构造一个长度为 \(k ...
- Tensorflow训练神经网络
以下代码摘自<Tensorflow实战Google 深度学习框架>. 由于这段代码包含了激活函数去线性化,多层神经网络,指数衰减学习率,正则化防止过拟合,滑动平均稳定模型等手段,涵盖了神经 ...
- 开源分布式工作流任务调度系统Easy Scheduler Release 1.0.2发布
Easy Scheduler Release 1.0.2===Easy Scheduler 1.0.2是1.x系列中的第三个版本.此版本增加了调度开放接口.worker分组(指定任务运行的机器组).任 ...
- android中service启动后台程序
Service是Android中一个类,它是Android四大组件之一,使用Service可以在后台执行长时间的操作( perform long-running operations in the b ...
- SpringBoot中AOP的配置
AOP目的: 面向切面编程(aspect-oriented programming,AOP)主要实现的目的是针对业务处理过程中的切面进行提取,诸如日志.事务管理和安全这样的系统服务,从而使得业务逻辑各 ...