search
LoginSignup
111
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

Organization

PHPerだが今日初めてGo言語に手を出してみる試み

この試みのゴール

  • 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行程度のコードを書く。

hello-world.go
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 のほうが時刻も一緒に出力してくれるので、fmtlog に置き換える:

import (
    "log"
    "os/exec"
)

date コマンドを実行するコードを書く:

call-command.go
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() の第二引数以降に与える。

call-command.go
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("コマンドが終了しました")
}

こんなかんじで、大まかなコマンドの実行方法がつかめたと思う。

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
What you can do with signing up
111
Help us understand the problem. What are the problem?