この試みのゴール
- Go言語でコマンドを叩けるようになる
つまづいたときのググり方
go
だけでググるとGo言語以外の情報も出てくるので「Go言語」や「go lang」で検索する。
Goをインストールする
Macで作ってLinuxにデプロイしようと思うので、Mac, Linux, Windowsにコンパイルできるように、クロスコンパイル可能な状態でGoをインストールする:
brew install go --cross-compile-common
とりあえず Hello World
適当にフォルダ作って…
cd ~/Desktop
mkdir my-first-go
cd my-first-go
そこにgoのファイル作って…
touch hello-world.go
エディタでそれを開いて、以下の10行程度のコードを書く。
package main
import (
"fmt"
)
func main() {
fmt.Print("Hello World\n")
}
おもむろに実行してみる
go run hello-world.go
Hello Worldって出ればOK。
コンパイルしてみよう
go build
ってやるだけでコンパイルできる
go build hello-world.go
ビルドしたファイルを実行してみる:
% ./hello-world
Hello World
こんな簡単にバイナリのコマンドが作れるなんてワクワクする!
さらに、Linux 64ビット用のバイナリを作ってみる
Mac用の hello-world
は消して、
rm -f hello-world
Linux 64ビット用のバイナリを作る:
GOOS=linux GOARCH=amd64 go build hello-world.go
できたら、適当なLinuxのマシンに送って、
scp hello-world sakura-vps:
Linuxにログインして、
ssh sakura-vps
実行してみる:
$ ./hello-world
Hello World
おー、出た!
Linuxからログアウトする
exit
コマンドを実行するだけのプログラムを作ってみる
とりあえず、Linuxコマンドさえコールできれば、Go言語でひかかってもなんとかなりそうなので、コマンドの呼び出し方を覚える。
hello-world.go
をコピーして call-command.go
を作る
cp hello-world.go call-command.go
コマンドを実行するには exec パッケージをインポートする:
import (
"fmt"
"os/exec"
)
あと、fmt.Print
もいいけど、 log
パッケージの log.Print
のほうが時刻も一緒に出力してくれるので、fmt
を log
に置き換える:
import (
"log"
"os/exec"
)
date
コマンドを実行するコードを書く:
package main
import (
"log"
"os/exec"
)
func main() {
log.Print("これはコマンドを実行するプログラムです!\n")
out, error := exec.Command("date").Output()
if error != nil {
log.Printf("エラー: %s", error)
return
}
log.Printf("現在時刻: %s", out)
}
実行してみる:
% go run call-command.go [18:23:40]
2013/12/04 18:24:24 これはコマンドを実行するプログラムです!
2013/12/04 18:24:24 現在時刻: Wed Dec 4 18:24:24 JST 2013
ちゃんと、現在時刻出ました!
エラーの場合どうなるか試してみる。
手っ取り早く date
コマンドを false
コマンドに置き換えてみる:
out, error := exec.Command("false").Output()
~~~~~ ここ
実行してみる:
% go run call-command.go [18:24:34]
2013/12/04 18:26:44 これはコマンドを実行するプログラムです!
2013/12/04 18:26:44 エラー: exit status 1
ちゃんとエラーの分岐に入りました!
引数を取るコマンドの実行
ls -la
のように引数をとるコマンドを試してみる。
コマンドの引数は exec.Command()
の第二引数以降に与える。
package main
import (
"log"
"os/exec"
)
func main() {
log.Print("これはコマンドを実行するプログラムです!\n")
out, error := exec.Command("ls", "-la").Output()
if error != nil {
log.Printf("エラー: %s", error)
return
}
log.Printf("%s", out)
}
実行してみる:
% go run call-command.go [18:29:46]
2013/12/04 18:30:58 これはコマンドを実行するプログラムです!
2013/12/04 18:30:58 total 4424
drwxr-xr-x 5 suin staff 170 Dec 4 18:08 .
drwx------+ 16 suin staff 544 Dec 4 17:59 ..
-rw-r--r-- 1 suin staff 278 Dec 4 18:29 call-command.go
-rwxr-xr-x 1 suin staff 2255544 Dec 4 18:08 hello-world
-rw-r--r-- 1 suin staff 77 Dec 4 18:02 hello-world.go
時間のかかるコマンド
時間がかかるコマンドは、終わるのを待たずに処理を進めたい場合があるので、そのやり方を覚える。
以下は、sleep 2
コマンドを実行する例:
package main
import (
"log"
"fmt"
"os/exec"
)
func main() {
log.Print("これはコマンドを実行するプログラムです!\n")
command := exec.Command("sleep", "2")
error := command.Start()
if error != nil {
panic(fmt.Sprintf("エラー1: %v", error)) // コマンドがなかった場合とか
}
log.Print("コマンドを開始しました")
error = command.Wait()
if error != nil {
panic(fmt.Sprintf("エラー2: %v", error)) // コマンドがエラーステータスで終了した場合
}
log.Print("コマンドが終了しました")
}
こんなかんじで、大まかなコマンドの実行方法がつかめたと思う。