うしろのこの本ください

なんでもかきます

Go言語お勉強備忘録

低レイヤーな言語も使えたら何かと良い事あるかなと言うことで、今流行りのGo言語を勉強していこうかなと。

ミリシタサーバもGoだしね。(アプリケーションの実装はUnityなのでC#かな?)

というわけでこちらを見ながらGoを触っていく。作りたいものは今動かしてるa&gの録画スクリプトのGo版。

参考

qiita.com

さて本題へ

インストールからリモート先へバイナリ転送して実行まで

環境:macOS Sierra(High Sierraにする必要あるのかな)

インストールはこの記事のではなく既にインストール済みのanyenvからgoenvで

詳しくは省略、ここを見れば多分いける

suguru03.hatenablog.com

GOPATHやらの設定が初見だとちょっと混乱したけどなんとかなった、コンパイル言語はこういうのが辛いのでインストーラがほしい。

さて次にHello Worldを表示するため作業用ディレクトリを作り移動、.goファイルも作る。

cd ~/Dev/Goproject/

//作業ディレクトリ作成
mkdir hello-go
cd hello-go

//Goファイル作成
touch main.go

普段プログラム書く時はDev/直下に言語別のディレクトリ作ってその中で作業って感じ。

main.goをテキストエディタIDEで開いて編集する。基本VSCodeC#を書く時はVisualStudioが今の開発環境。

以下の様に書いてみる。

package main //Goでは必ずどこかのパッケージに属してないとだめらしい

import "fmt" //Goはパッケージ管理ツールがビルトインされているためimport ~ でモジュールを使える

func main() { //main関数が最初に実行される

  fmt.Println("Hello World!")

}

書いたら保存して以下のコマンドで実行できる。

go run main.go

Hello World!って表示されるはず。でなければGOPATHとかの環境設定を見直す。

次にコマンドを叩くプログラムを書いてみる、command.goを同じディレクトリに作成して中身を編集。main.goをコピーで良い。

cp main.go 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)

}

fmtよりlogのほうが色々出力してくれるらしいので変更、goからlinuxコマンドを叩くのはos/execパッケージを使う。

上のプログラムではoutに実行結果、errorにエラーだった場合の結果が入るためerrorがnilじゃない場合(errorに何か入っている場合)エラー出力する。

Goにはtry~catch構文がないが、関数の戻り値を複数指定することが出来るためこれでエラーハンドリングする。deferという構文を使えばtry~catch的な書き方出来るらしいけど今回はスルーで。

上記プログラムを実行すると以下の用に出力されるはず。

go run command.go

2018/04/15 22:40:33 これはコマンドを実行するプログラムです
2018/04/15 22:40:33 現在時刻: 2018年 4月15日 日曜日 22時40分33秒 JST

liunxコマンドのdateを実行した結果をlogパッケージのlog.Printfで出力している。これだけできれば後は必要な実行ファイルを分割して作った後メインからそれぞれ定期実行すれば簡単なタスクツールは作れるね。

ここまで出来たらコンパイルしてバイナリファイルを作ってみる。以下を実行すると.go拡張子のとれた実行ファイルが生成される。

go build command.go

実行ファイルは自動でmacOS用にコンパイルされているためそのまま実行可能

 ./main

2018/04/15 22:54:43 これはコマンドを実行するプログラムです
2018/04/15 22:54:43 現在時刻: 2018年 4月15日 日曜日 22時54分43秒 JST

最後に常駐させているRaspberry Piに転送した後SSHで接続し同様に実行できるか確認する。ここは完全に個人環境に依存しているので適宜読み替え必須。

自分の場合Raspberry Pi 3 model BなのでOSはARMの32bit。コンパイルをARM32bit向けにするためオプションをつけてbuildを実行する。その前に今作ったバイナリファイルの削除を先にする。

rm -f command

各OS向けのクロスコンパイルの設定はこちらから

qiita.com

suinさんありがとう!

以下を実行

GOOS=linux GOARCH=arm go build command.go

同じようにcommandファイルが生成されるが、中身はARM32bit用になっている。これをRaspberry Piに転送する。

scp command pi@[転送先ip]:

実行結果

command                                       100% 2179KB   3.3MB/s   00:00

思ったよりファイルサイズがでかい。最適化とかあるのかな?

とりあえず実行できるか確認するためSSHでリモート接続。

ssh pi@[転送先ip]

接続できたら実行、結果確認

pi@raspberrypi:~ $ ./command
2018/04/15 23:08:24 これはコマンドを実行するプログラムです
2018/04/15 23:08:24 現在時刻: Sun 15 Apr 23:08:24 JST 2018

できた!

おわり

ゴルーチンやチャネルなど並列処理が簡単に実装できる仕組みが標準であるので、今後はそれを中心に学んでいこうかな。集計とかスクレイピングにも強そうだ。加減しないと負荷ひどくなりそうだけど。

ここまで出来たらもう開発始められるので、さっさと録音プログラム書いてラズパイに仕事あげたい。週末に数時間のペースでも一ヶ月かからないはず。

今日はここまで

では