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 动态代码评估:代码注入
随机推荐
- BZOJ 2668: [cqoi2012]交换棋子
2668: [cqoi2012]交换棋子 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1112 Solved: 409[Submit][Status ...
- Alpha 冲刺 —— 十分之七
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 学习MSI.CUDA 试运行软件并调试 ...
- USACO Section 1.5 Superprime Rib 解题报告
题目 题目描述 超级素数的定义如下:如果有个素数我们从右往左依次去掉一位数,每次去掉一位数剩下的数仍然是素数,那么我们称这个数是超级素数.例如7331,这是一个素数,从右往左依次去掉一位数733, 7 ...
- 【agc019C】Fountain Walk
Portal --> agc019C Description 有一个\(10^8*10^8\)的网格图,一格距离为\(100\),第\(x\)条竖线和第\(y\)条横线的交点记为\((x,y)\ ...
- 图像处理之CSC色彩转换
1 YUV域介绍 根据三基色原理,任意一种色光F都可以用不同分量的R.G.B三色相加混合而成,即F = r [ R ] + g [ G ] + b [ B ],其中r.g.b分别为三基色参与混合的系数 ...
- Leetcode 503. 下一个更大元素 II
1.题目描述 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应 ...
- Html和websocket初识
一.web框架 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. import socket def handle_request(c ...
- python的str()字符串类型的方法详解
字符串一旦创建,不可修改,一旦修改或者拼接,都会造成重新生成字符串,因为内存存数据是一个挨着一个存的,如果增加一个字符串的话,之前的老位置只有一个地方,不够,这是原理性的东西,在其他语言里面也一样 7 ...
- K8S调度之pod亲和性
目录 Pod Affinity Pod亲和性调度 pod互斥性调度 Pod Affinity 通过<K8S调度之节点亲和性>,我们知道怎么在调度的时候让pod灵活的选择node,但有些时候 ...
- python中__init__()、__new__()、__call__()、__del__()用法
关于__new__()的用法参考: http://www.myhack58.com/Article/68/2014/48183.htm 正文: 一.__new__()的用法: __new__()是在新 ...