goを1.7に上げてから、gocodeが動かなくなったりもしました
go1.6.2 -> go1.7でgocodeが動作しない
手元のmacの環境のgoを1.7に上げたところ、gocodeが上手く動作しなくなった。 (macportsを使っている)
$ sudo port selfupdate $ sudo port upgrade go $ go version go version go1.7 darwin/amd64
以下の様な感じの出力を返す様になってしまった。
$ cat xxx.go | gocode -debug autocomplete /tmp/xxx/xxx.go c89 Found 1 candidates: PANIC PANIC PANIC
対応
以下を参考にして、gocodeをcloseした後、インストールしなおしたら直った。
$ gocode close $ go get -u github.com/nsf/gocode
上手く動作している。
$ cat xxx.go | gocode -debug autocomplete /tmp/xxx/xxx.go c89 Found 7 candidates: func Command(name string, arg ...string) *exec.Cmd func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd func LookPath(file string) (string, error) type Cmd struct type Error struct type ExitError struct var ErrNotFound error
memo
/tmp/xxx/xxx.go
package main import ( "os/exec" ) // cancel by context func main(){ cmd := exec.//|ここにカーソル }
deferのタイミングで関数の戻り値を変えたい場合には、named return使うしかないのかも?
はじめに
例えば、以下の様な状況。
- deferで何らかの後片付けをする。
- この後片付けのタイミングでerrorが発生。
この時、deferの中の処理で発生したerrorを戻り値として返したい。このような事をしようとした場合にnamed returnを使うしかなかったという話。
sample
f()の後片付けの最中のcleanup()でerrorが発生する場合。
func f()(string, error) { s, err := g() defer cleanup(s) return s, err } func g()(string, error) { return "ok", nil } func cleanup(s string) error { return fmt.Errorf("hmm") }
もちろんこの時の出力結果は以下の様になる。
fmt.Println(f())
// ok, <nil>
deferの中で値を書き換えてもダメ
以下のように書き換えても、やっぱり戻り値はnilになってしまう。
func f()(string, error) { s, err := g() defer func(){ if cerr := cleanup(s); err == nil && cerr != nil { err = cerr } }() return s, err }
出力結果
fmt.Println(f())
// ok, <nil>
named returnを使うと大丈夫
named returnは個人的には好きじゃないのでなるべくなら避けたいものだったのだけれど。今回に限っては必要性を認めざるを得ない感じ。
func f()(s string, err error) { s, err = g() defer func(){ if cerr := cleanup(s); err == nil && cerr != nil { err = cerr } }() return s, err // returnだけでもok }
今度は発生したerror(hmm)を返す。
fmt.Println(f())
// ok hmm
ところで以下の様に書いてもcompile通っちゃうのが嫌な感じ。
あんまりないことではあるけれど、g()を呼び忘れたような状況。
func f()(s string, err error) { // s, err = g() defer func(){ if cerr := cleanup(s); err == nil && cerr != nil { err = cerr } }() return s, err }
zero値で初期化されちゃってるので。
fmt.Println(f())
// hmm