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

20 Organizing Go code 组织go代码的更多相关文章

  1. 组织Golang代码

    本月初golang官方blog(需要自己搭梯子)上发布了一篇文章,简要介绍了近几个月Go在一 些技术会议上(比如Google I/O.Gopher SummerFest等)的主题分享并伴有slide链 ...

  2. ECLIPSE使用HG插件去上载 GOOGLE.CODE下的代码

    ECLIPSE使用HG插件去上载 GOOGLE.CODE下的代码 www.MyException.Cn   发布于:2012-09-10 22:20:12   浏览:112次 0   ECLIPSE使 ...

  3. 重读 code complete 说说代码质量

    重读code complete 说说代码质量 2014年的第一篇文章本来计划写些过去一年的总结和新年展望,但是因为还有一些事情要过一阵才能完成,所以姑且不谈这个,说说最近重读code complete ...

  4. C# ORM—Entity Framework 之Code first(代码优先)(二)

    一.Entity Framework Code first(代码优先)使用过程 1.1Entity Framework 代码优先简介 不得不提Entity Framework Code First这个 ...

  5. Sublime Text3—Code Snippets(自定义代码片段)

    摘要 程序员总是会不断的重复写一些简单的代码片段,为了提高编码效率,我们可以把经常用到的代码保存起来再调用. 平时用sublime安装各种插件,使用Tab键快速补全,便是snippets(可译为代码片 ...

  6. 使用visual studio code调试php代码

    这回使用visual studio code折腾php代码的调试,又是一顿折腾,无论如何都进不了断点.好在就要放弃使用visual studio code工具的时候,折腾好了,汗~ 这里把步骤记录下来 ...

  7. #001 如何组织JS代码

    如何组织JS代码 有没有这样的经历,在编写代码的时候,因为功能简单,写的时候比较随意,所有的JS代码都放在一个文件里面,但是随着功能的增加,发现代码很乱,不好维护. 简单的整理了一下,目前对已有项目的 ...

  8. eclipse 编辑器支持 Code Minings(代码挖掘)功能

    Java 编辑器支持 Code Minings 功能 Java 编辑器现在可以在 Java 元素的上方以“装饰文本”的形式显示实现和引用的数量,即 Code Minings(代码挖掘)功能 启用路径: ...

  9. Dynamic Code Evaluation:Code Injection 动态代码评估:代码注入

随机推荐

  1. 获取远程图片的Blob资源

    原文地址:http://www.cnblogs.com/JimmyBright/p/7681092.html 思路:js获取远程资源的blob会涉及到跨域的问题,所以需要中转一下,具体是使用php的c ...

  2. Mybatis笔记八:MyBatis中#{}和${}的区别

    先给大家介绍下MyBatis中#{}和${}的区别,具体介绍如下: 1. $将传入的数据直接显示生成在sql中 2. #方式能够很大程度防止sql注入. 3.$方式无法防止Sql注入. 4.$方式一般 ...

  3. 【BZOJ2989】数列(二进制分组,主席树)

    [BZOJ2989]数列(二进制分组,主席树) 题面 BZOJ 权限题啊... Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即g ...

  4. 模板:快速傅里叶变换(FFT)

    参考:http://blog.csdn.net/f_zyj/article/details/76037583 如果公式炸了请去我的csdn博客:http://blog.csdn.net/luyouqi ...

  5. 51nod 1353 树 | 树形DP经典题!

    51nod 1353 树 | 树形DP好题! 题面 切断一棵树的任意条边,这棵树会变成一棵森林. 现要求森林中每棵树的节点个数不小于k,求有多少种切法. 数据范围:\(n \le 2000\). 题解 ...

  6. Go interface{}、类型断言

    在 golang 中 interface{} 可用于向函数传递任意类型的变量, 但在函数内部使用的话, 该变量的类型就是 interface{}, 也称为空接口类型 比如我们定义一个函数, 输出字符串 ...

  7. nginx 配置 phpmyadmin

    server { listen 8092; server_name *.xxx.com; root /home/users/cuijian04/odp302/app/phpmyadmin; set $ ...

  8. Unhandled rejection RangeError: Maximum call stack size exceededill install loadIdealTree

    npm安装时候报这个错误,解决方法如下: 删除项目中的 package-lock.json 文件 和 node_modules 文件夹,然后再尝试 npm install 详细参考

  9. [BZOJ1878][SDOI2009] HH的项链 (树状数组)

    link 一道简单题. 不用可持久化. 对于统计颜色个数,可以看与其颜色一样的前一个位置. 设$las(i)$表示其与$i$颜色相等的上一个位置. 则对于二元组$(l,r)$,其答案为$\sum_{i ...

  10. Laravel 返回 JSON 格式

    第一种方法: 第一步.编写 BaseRequest首先我们需要构建一个 BaseRequest 来重写 Illuminate\Http\Request ,修改为默认优先使用 JSON 响应: app/ ...