Emacs for Go

Stella981
• 阅读 859

In this post I'm going to explore customizing Emacs to make hacking on Go a little more fluid. This is a living document and will probably be updated as I discover new modes and tools.

The Emacs modes I currently use are: go-mode, oracle, goflymake, and gocode.

I break out my Emacs configuration into language or package specific configuration files. This keeps /emacs.d/init.el pretty lean as all it is doing is loading in other configuration files with calls to load like this: (load "/.emacs.d/go.el").

go-mode

go-mode is the first mode we'll look at. It provides syntax highlighting, default indentation matching the golang standards and gofmt, the ability to add and remove imports, the ability to browse documentation and support for integrating godoc and godef.

To enable go-mode add the following go.el:

(require 'go-mode)(add-hook 'before-save-hook 'gofmt-before-save)

Let's start by looking at arguably the most fundamental capability added by go-mode - managing imports. go-mode adds three functions of note: go-import-add, go-remove-unused-imports and go-goto-imports.

go-import-add is bound to C-c C-a by default. If you call go-import-add with a prefix it will prompt you to provive an alternate name for the import. To do this type C-u C-c C-a. If no list of imports exists go-import-add will create one. If the import you are adding is currently in the list of imports but commented out it will be uncommented. Pretty good stuff for a very common pattern. One point to keep in mind is that go-import-add will only work once you have a package declaration in place.

go-remove-unused-imports, as the name implies, removes all unused imports. As with_go-import-add_ calling go-removed-unused-imports with a prefix will change the default behavior - commenting out unused imports instead of removing them. By default isn't bound to anything by default. So let's start by setting up a keybinding specific to go-mode in ~/.emacs.d/go.el

(add-hook 'go-mode-hook '(lambda ()
  (local-set-key (kbd "C-c C-r") 'go-remove-unused-imports)))

Now we can use C-c C-r to remove all unused imports, or C-u C-c C-r to comment out unused imports.

go-goto-imports is a pretty nifty helper function that will move the point to the imports block. By default it isn't bound to any keys by default so let's hop back into_~/.emacs.d/go.el_ and add a keybinding for it. I set it to C-c C-g as a mnemonic of "goto"

(add-hook 'go-mode-hook '(lambda ()
  (local-set-key (kbd "C-c C-g") 'go-goto-imports)))

gofmt formats the current buffer according to the gofmt rules. By default it isn't bound to anything. I bind gofmt in two ways: C-c C-f as a mnemonic for "format" allowing me to format the buffer without saving and also with a "before-save-hook" so that the buffer is always correctly formatted when I save.

(add-hook 'go-mode-hook '(lambda ()
  (local-set-key (kbd "C-c C-f") 'gofmt)))(add-hook 'before-save-hook 'gofmt-before-save)

godoc shows the go documentation for a given package. Note, godoc depends on the godoc utility. It must be installed and on your $PATH. To install it run: go get code.google.com/p/go.tools/cmd/godoc. By default godoc isn't bound to anything. I map this to C-c C-k as a mnemonic for man -k or aproposgodoc will use whatever token is under the point as the search term but will promt you if you want to search godoc for something else. Try moving to one of your imports and hitting 'C-c C-k'.

(add-hook 'go-mode-hook '(lambda ()
  (local-set-key (kbd "C-c C-k") 'godoc)))

godef is a really nifty tool that parses go code and enables you to quickly jump the definition of any symbol or read its description. As with godoc, godef must be installed and on your $PATH. To install godef run: go get code.google.com/p/rog-go/exp/cmd/godefgo-mode provides two functions for interacting with godefgodef-describe and godef-jump.

godef-describe is insanely useful and will give you information about the symbol you're looking at. By default is is bound to C-c C-d. If the point is on a function call_godef-describe_will show its full definition (parameter name and type, return type). If the point is on a struct godef-describe will show all members of the struct.

godef-jump will jump the defintion of the expression at the point. It is bound to C-c C-j. Remember that C-x  will take you back to the previous buffer once you're done reading the definition of whatever you're looking at.

go oracle

go oracle is an external source analysis tool that let's you answer questions like: "what interfaces does this type implement?", "which types implement this interface?", "who is listening for events on this channel?", "what are the possible callers of this function?"...etc. I highly recommend reading the _go oracle_documentation in depth - it is an advanced tool and I'm only scratching the surface here. As the documentation states, this tool is a work in progress. Rough edges are expected but the benefits are well worth it.

To install go-oracle run: go get code.google.com/p/go.tools/cmd/oracle which will install the tool in your $GOPATH/bin directory. However, the emacs bindings expect to find go-oracle in $GOROOT/bin and not $GOPATH/bin so you'll need to manually move the binary to the right place: mv $GOPATH/bin/oracle $GOROOT/bin/. Next we'll need to configure emacs to load the bindings. Add something like the following to go.el -- obviously with $GOPATH matching your own $GOPATH. The second line ensures go-oracle-mode is enabled whenever editing go code.

(load "$GOPATH/src/code.google.com/p/go.tools/cmd/oracle/oracle.el")(add-hook 'go-mode-hook 'go-oracle-mode)

Before using go-oracle you must set the 'scope of analysis'. This is done by calling the go-oracle-set-scope function M-x go-oracle-set-scope and listing one or more packages or import paths of packages. In the simplest case this is the 'main' package of your go application. As the tool states, bigger scopes are better since the tool will analyze more code - but it might also slow down the oracle a bit. If you need to specify multiple packages simply separate them with a space. An example, from the documentation, of an analysis scope is: fmt code.google.com/p/go.tools/cmd/oracle which includes the fmt package and also the_go-oracle_ package for analysis.

To start getting a feel for go-oracle move the point to a function and enter _C-c C-o <_to see what calls this function. To see the possible sends/receives on a channel move the point to the channel and run _C-c C-o c_.By default _go-oracle-mode_ sets up the following keybinds. Note: keybindings with '<' and '>' such as _go-oracle-callers_may not work on Mac OS X so you might need to rebind them.

C-c C-o <       go-oracle-callers
C-c C-o >       go-oracle-callees
C-c C-o c       go-oracle-peers
C-c C-o d       go-oracle-definition
C-c C-o f       go-oracle-freevars
C-c C-o g       go-oracle-callgraph
C-c C-o i       go-oracle-implements
C-c C-o p       go-oracle-pointsto
C-c C-o r       go-oracle-referrers
C-c C-o s       go-oracle-callstack
C-c C-o t       go-oracle-describe

goflymake

goflymake is a wrapper around the go tool providing flymake compatible syntax checking for go source. Since goflymake is actually compiling the source we get full compile and link checking as well.

To install the goflymake wrapper run go get -u github.com/dougm/goflymake. Next we'll need to configure emacs. Add the following to go.el obviously replacing $GOPATH with the location of your go workspace.

(add-to-list 'load-path "$GOPATH/src/github.com/dougm/goflymake")(require 'go-flymake')

The error checking provided by goflymake looks like the following. Note: unused imports are highlighted as an error, as is the incorrect call to http.Get()

Emacs for Go  Emacs for Go

gocode

gocode provides context-sensitive autocompletion. To install gocode run: go get -u github.com/nsf/gocodegocode alsp depends on either auto-complete-mode or_company-mode_. I went with company-mode and company-mode-go. Both packages are available in ELPA so simply run: M-x package-install RET company-go

Next we need to automatically load company-mode whenever go-mode is loaded and also configure company-go as its backend. Add the following to go.el.

(add-hook 'go-mode-hook 'company-mode)(add-hook 'go-mode-hook (lambda ()  (set (make-local-variable 'company-backends) '(company-go))
  (company-mode)))

The auto-completion provided by gocode and company-go looks like the following (after searching for "Get"). Notice the function definition in the minibuffer.

Emacs for Go

That's it for now. Happy hacking.

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这