読者です 読者をやめる 読者になる 読者になる

Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

io.ioutilを使って一時ファイルをつくる

golang

ツールを作る際、何かと必要な一時ファイル。
GO言語では、io.ioutilを使ってつくる事ができます。

実際のところ

一時ファイルを作る場合はioutil.TempFileを使います
ioutil - The Go Programming Language

公式サンプルを元に、一通りの挙動をするスクリプトは以下の通り。

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
)

func main() {
	content := []byte("temporary file's content")
	tmpfile, err := ioutil.TempFile("", "example")
	if err != nil {
		log.Fatal(err)
	}

	defer os.Remove(tmpfile.Name())
	defer tmpfile.Close()

	if _, err := tmpfile.Write(content); err != nil {
		log.Fatal(err)
	}

	fpath := tmpfile.Name()
	fmt.Println(fpath)
	if f, err := ioutil.ReadFile(fpath); err != nil {
		log.Fatal(err)
	} else {
		fmt.Println(string(f))
	}
}

ファイルを読み込む際、どこかの莫迦のようにTempFileを生成した変数でReadFile関数を読まないようにして下さいね(白目


実行してみると、都度都度ファイルを作ってるらしい事がわかります

$ go run ioutilTest.go 
/var/folders/02/546lp7s57l93kzydhj2dtyzr0000gn/T/example782409817
temporary file's content

$ go run ioutilTest.go 
/var/folders/02/546lp7s57l93kzydhj2dtyzr0000gn/T/example076921445
temporary file's content

if構文の中だけで通用する変数を別途設定できる

golang

GO言語ではif文の中だけで通用する変数を別途設定できます。

実際のところ

公式サンプルから。
指定数分、乗数を掛けるが最後の引数を突破した場合はそれに従う……みたいな
ある種フィルターめいた関数は以下の通り。

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	}
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

従属するelseでも変数は利用可能です。

参考もと

A Tour of Go

Bash環境において"$_"は最後にマッチした変数を拾う

bash

Bash環境において"$_"は最後にマッチした変数を拾います。

実際のところ

以下のようなコマンドを叩いたとします。

 $ mv ~/tmp/hoge /Users/shuzo_kino/dev/src/
$ cd $_

この時、"$_"がマッチするのはどっちでしょうか?
……正解は後者。
これならmvした後に移動先に飛ぶことができるので便利ですね。

testingパッケージの"Example~"記法だと実行例をドキュメントに記載できる

golang

testingパッケージの"Example~"記法だと実行例をドキュメントに記載できます。
ユーザが頻繁に利用するタイプの関数なら、付けておくと親切で良いかと思います。

実際のところ

実行対象の内容は前回のと同じです。

func ExampleSomething() {
	fmt.Println(Something(1, 4))
	// Output: 5
}

実行すると、こんな感じ

$ go test hoge
ok  	hoge	0.007s

駄目なバージョンとして
先程の"Output: 5"を、
正しい"Output: 6"にしてみると……

$ go test hoge
--- FAIL: ExampleSomething (0.00s)
got:
5
want:
6
FAIL
FAIL	hoge	0.007s

これだと何の旨みがあるのか全く分かりませんね。
godocと連携すると、公式で見られるような"ドキュメント中に記載できる実行例"として扱う事ができます。
f:id:shuzo_kino:20170419224148p:plain
テストもドキュメント化も兼ねていて実際便利!

Golangでテストを始める

golang

GoLangでテストをやるには"testing"パッケージをつかいます。
公式では、余計な外部パッケージを使わずデフォのものを推奨しているので、それに従っておきます。

実際のところ

デフォでは"$GOPATH/src"以下にあるフォルダを対象に実行されます。
今回は"hoge"を対象に。
外部パッケージ化する場合、"github.com/USERNAME/PACAKGENAME"みたいなディレクトリ構造がお作法のようです。

$ cd $GOPATH/src
$ tree -L 3 hoge/
hoge/
├── hoge.go
└── hoge_test.go

0 directories, 2 files

とりあえず、最小構成のテスト用スクリプトはこちら。
まずはhoge.go

package hoge

func Something(a int16, b int16) int16 {
	return a + b
}

テストのhoge_test.go。
"パッケージ名_test"という命名規則に従う事で、後述のテストコマンドがスムーズに動きます。

package hoge

import "testing"

//テストをやってみたい
func TestSomething(t *testing.T) {
	if Something(1, 3) != 4 {
		//失敗したケース。
		//GoLangではエラーはすぐに処理という文化らしいので
		t.Fatal("something(1,3) should be 4, but Don't matched")
	}
}

では、実行してみましょう。

$ go test PACKAGENAME

という記法なので、以下のように叩いてみると……はい、返り値の型が不正で駄目ですね。
こういうトコロもみてくれます(白目

$ go test hoge
# hoge
hoge/hoge.go:4: cannot use a + b (type int16) as type int in return argument
FAIL	hoge [build failed]

気を取り直して、intをint16にして再度やると

$ go test hoge
ok  	hoge	0.006s

つづき

ドキュメント化時に実行例つきにしたい場合は、"Example~"記法です。
shuzo-kino.hateblo.jp

GoLang用REPL「gore」

golang

GoLangにはサードパーティ提供のREPL「gore」があります。
毎回毎回コンパイルしなくとも動作検証ができます。

実際のところ

導入

$ go get -u github.com/motemen/gore

公式で周辺ツールの導入も勧められているので、
ついでに導入しておきます。

$ go get -u github.com/nsf/gocode
$ go get -u github.com/k0kubun/pp # or github.com/davecgh/go-spew
$ go get -u golang.org/x/tools/cmd/godoc

動作

試しに動かしてみましょう。

$ gore
gore version 0.2.6  :help for help
gore> var something int16
gore> something = 10
10
gore> something + 20
30
gore> something
10
gore> something = something + 20
30

さらに、現状の内容をGOスクリプトとして吐き出すオプションが備わっています。
ためしに":print"を実行すると、以下のような内容で出てきます。

package main

import "fmt"

func __gore_p(xx ...interface{}) {
    for _, x := range xx {
        fmt.Printf("%#v\n", x)
    }
}
func main() { var something int16; something = 10; something = something + 20 }

中断

中断するには"Ctrl-D"。
Pythonと同じですね。

外部のファイルやパッケージを読み込むには?

$ 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

参考もと

github.com

Scrapboxでアイディアや情報を相互に連携させる

備忘録

Scrapboxはアイディアやメモ書きを溜めておくのに丁度いいツールです。
Google Keepなんかがあるみたいです。

登録はよくある他サービスと連携できるタイプ。
私は仕事で使うことになったので、G-Suiteのを連携しときました。
scrapbox.io
登録すると、こんな画面が。
……なんだか妙に殺風景ですね……。
f:id:shuzo_kino:20170416231908p:plain
通常のユースケースだとチーム毎にページをつくって、
そこに情報を集約する感じなようです。

とはいえ社内のを共有するわけにもいかないので……公式サンプル集の中から、不動産屋さんの想定ページを見てみましょう
カード形式のページ群を確認できます。
f:id:shuzo_kino:20170416233119p:plain
ためしに、そのうちひとつを見てみると……末尾の方にリンクがペタペタ貼られています。
f:id:shuzo_kino:20170416231918p:plain
このリンク集がツールの肝で、数が増えると色々と相互作用がでて凄い事になりそうです。
ある種ブレスト的といいますか……。
方法はカンタンで、他ページとの連携は"[ ]"で囲むか、"#"をつけてあげるだけでOKです。

#すごい思いつき
[すごい思いつき]

他にもアイコンを埋め込んだり更新があったらSlackに通知と色々機能があります。
詳しい方法は公式のサンプルを参照して下さい。
Scrapbox ヘルプ - Scrapbox