40
28

More than 3 years have passed since last update.

みんGo学習メモ〜コード補完もできるREPL「gore」を使ってみた

Last updated at Posted at 2018-04-13

https://github.com/motemen/gore
GoでREPLといえばgoreとのことなので、早速使ってみる。

インストールする

まずはgo getでインストール

GO111MODULE=off go get -u github.com/motemen/gore/cmd/gore

READMEのInstallation[https://github.com/motemen/gore#installation]
を見ると以下もインストールすることが推奨されているので、
こちらもgo getしておく。

# 入力補完
GO111MODULE=off go get -u github.com/mdempsky/gocode

# 出力ハイライト
GO111MODULE=off go get -u github.com/k0kubun/pp # or github.com/davecgh/go-spew/spew

【2019/12 追記】

APIドキュメントの参照のために以前はgodocが必要だった。
現在は不要(go docコマンドを使用)なので削除。
Fix :doc command in Go 1.12 by rzyns · Pull Request #117 · motemen/gore
drop godoc requirements from README.md by Songmu · Pull Request #142 · motemen/gore

使ってみる

以下で実際に使ってみる。
ターミナル上でとりあえずgoreと打ってみると、以下のような出力となる。

$ gore
gore version 0.4.1  :help for help
gore> 

早速REPLが起動しているよう。
まずは促されるがままに:helpと打つ。

gore> :help
    :import <package>     import a package
    :type <expr>          print the type of expression
    :print                print current source
    :write [<file>]       write out current source
    :clear                clear the codes
    :doc <expr or pkg>    show documentation
    :help                 show this help
    :quit                 quit the session

利用できるコマンドの一覧が出力されたので、ひとつずつ試していこうと思う。

:importを使ってみる

gore> :import encoding/json
gore> b, err := json.Marshal(nil)
[]uint8{
  0x6e, 0x75, 0x6c, 0x6c,
}
nil

:importコマンドは説明の通り、goreのセッション内で使用するパッケージの
インポートを行う。

上の例では事前にimportすることでencoding/jsonパッケージを使用できるようにしている。
事前にimportしない場合は以下のような出力になる。

gore> b, err := json.Marshal(nil)
# command-line-arguments
/tmp/991290791/gore_session.go:10:25: undefined: json
error: exit status 2
exit status 2

:typeコマンド 【2019/12 追記】

Implement type command by itchyny · Pull Request #127 · motemen/gore

上記PRで実装された。引数に変数などを渡すと、その変数の型を返してくれる。

gore> b, err := json.Marshal(nil)
[]uint8{
  0x6e, 0x75, 0x6c, 0x6c,
}
nil
gore> :type b
[]byte
gore> :type err
error

:docコマンドを使う

次に:docコマンドを使うと、godocのドキュメントがひける。
REPL上での出力は以下のような感じ。

gore> :doc json.Marshal
package json // import "encoding/json"

func Marshal(v interface{}) ([]byte, error)
    Marshal returns the JSON encoding of v.

...

パッケージ内の関数は.繋ぎで入力してもうまくいくよう。
また、変数のメソッドなども、変数のまま入力すればうまくいく。
とても便利。

これも事前にimportしておく必要がある。
importしてなかった場合は以下の出力となる。

gore> :doc json.Marshal
error: doc: cannot determine the document location

:printコマンド、:writeコマンド、:clearコマンド

試しに打ってみると、以下のような出力となる。

gore> :print
package main

import (
    "github.com/k0kubun/pp"
    "encoding/json"
)

func __gore_p(xx ...interface{}) {
    for _, x := range xx {
        pp.Println(x)
    }
}
func main() { b, err := json.Marshal(nil) }

これを:writeコマンドによってファイル保存できる。

gore> :write example.go
Source wrote to example.go
:clearコマンド 【2019/12 追記】

Implement clear command by itchyny · Pull Request #119 · motemen/gore

ここで追加された:clearコマンドを使う。

gore> :clear
gore> :print
package main

import "github.com/k0kubun/pp"

func __gore_p(xx ...interface{}) {
    for _, x := range xx {
        pp.Println(x)
    }
}
func main() {}

セッション中に定義したものを初期化できるようになった。
(上記ではfunc main()内にに定義していたb, err := json.Marshal(nil)が消えて
初期化されたことが確認できる)

【2019/12 追記ここまで】

:quitコマンドでgoreセッションから抜け、
先ほど保存したファイルの中身を確認。

gore> :quit
$ cat example.go
package main

import (
        "github.com/k0kubun/pp"
        "encoding/json"
)

func __gore_p(xx ...interface{}) {
        for _, x := range xx {
                pp.Println(x)
        }
}
func main()     { b, err := json.Marshal(nil) }

:printコマンドで出力したものと同じ内容となっていることが確認できる。

以上、ここまでがgoreセッション内でのコマンドとなる。
これらを駆使して快適なREPLライフを目指す。

goreコマンド自体のオプション利用

まずは--helpを渡して実行してみる。

$ gore --help
Usage of gore:
  -autoimport
        formats and adjusts imports automatically
  -context string
        import packages, functions, variables and constants from external golang source files
  -pkg string
        specify a package where the session will be run inside

-autoimportオプション

:importコマンドを使う手間を省略できるというもの。

$ gore -autoimport
gore version 0.2.6  :help for help
gore> b, err := json.Marshal(nil)
[]uint8{
  0x6e, 0x75, 0x6c, 0x6c,
}
nil

-contextオプション

指定されたgoのソースファイルで使われているパッケージ群を
まとめて事前にインポートできる。

先ほど:writeコマンドで作成したexample.goを例として使用する。

$ gore -context example.go 
gore version 0.4.1  :help for help
added file example.go
gore> :print
package main

import (
    "github.com/k0kubun/pp"
    "encoding/json"
)

func __gore_p(xx ...interface{}) {
    for _, x := range xx {
        pp.Println(x)
    }
}
func main() {}

example.goで使用していたencoding/jsonをデフォルトでインポートすることができた。

-pkgオプション

-contextオプションと同様に.goファイルからパッケージの事前インポートができる。
こちらはパッケージ名を指定する。

先ほどのexample.goを作業リポジトリを作って配置し以下のようにする。
(例: github.com/Ken2mer/example)

$ gore -pkg github.com/Ken2mer/example

そして:printコマンドを打つとさきほど-contextオプションの時と
同じく以下の出力結果となる。

gore> :print
package main

import (
    "github.com/k0kubun/pp"
    "encoding/json"
)

func __gore_p(xx ...interface{}) {
    for _, x := range xx {
        pp.Println(x)
    }
}
func main() {} 

こちらは複数ファイルを持つパッケージなどに対し一括でインポートできるので有用そう。

おわりに

以上で使い方が網羅できたかと思います。

簡単な動作確認のために、わざわざmain.goを作成してgo runと実行していたところが
コマンド一発で済ませられるようになった印象を受けました。

このツールの作者自身も

REPL といいつつ実は裏ではそれまでの入力を順番に実行するソースコードを生成して go run しているだけ

とおっしゃっています。

シンプルで非常に使いやすいので、これからもお世話になりたいと思います。
どんどん使っていきます。

【2019/12 追記】

40
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
28