- 投稿日:2020-11-23T23:56:38+09:00
go modやgo getやgo mod vendorとは何か?
Goを始めたばかりでgo modやgo getやgo mod vendorがよくわかってないので、そのメモ
間違ってる可能性はあるので、そこはご了承ください
go.modファイルはGemfileやpackage.jsonみたいなもので、go.sumファイルはGemfile.lockやpackage.lock.jsonみたいなもの
go get パッケージ名
で、go.modとgo.sumにパッケージ名が書き込まれる
go get -u パッケージ名
が、go.modとgo.sumに書いてあるパッケージのバージョンを更新してくれるつまり、Gemfileに欲しいgemを追記してbundle installしてgemを取り込むのとは手順が逆で、欲しいパッケージをgo getしてそしたら自動的にgo.modやgo.sumに書き込まれる
go mod vendor
でgo.modにファイルに記載されているパッケージを、vendor以下にコピーしてくれる
- 投稿日:2020-11-23T20:43:06+09:00
Grove - Temperature&Humidity Sensor(DHT11)をRaspberry Piで使用する
はじめに
HAT基盤と温度センサーを買ったのはよかったけど、動かしていなかったので、動作検証代わりに行った。
お値段等
* 千石電商 Grove Base Hat for Raspberry Pi ¥1304
* Grove - デジタル温度・湿度センサー ¥662Grove Base Hat for Raspberry Piの準備
Seeed Studioの商品ページを参考に
以下のコマンドを入力してセットアップをする。curl -sL https://github.com/Seeed-Studio/grove.py/raw/master/install.sh | sudo bash -s -実行しばらく待つと以下のメッセージが表示される。
Successfully installed grove.py-0.6 ####################################################### Lastest Grove.py from github install complete !!!!! #######################################################Grove - Temperature&Humidity Sensor(DHT11)を動作する。
Seeed Studioの商品ページを参考にして、
センサーをHat基盤のPWMに接続をする。以下のコマンドでライブラリをインストールする。
git clone https://github.com/Seeed-Studio/Seeed_Python_DHT.git cd Seeed_Python_DHT sudo python setup.py installインストールしたら以下の通りメッセージが表示される。
Installed /usr/local/lib/python2.7/dist-packages/seeed_python_dht-0.0.1-py2.7.egg Processing dependencies for seeed-python-dht==0.0.1 Finished processing dependencies for seeed-python-dht==0.0.1サンプルコードがgitからコピーしたフォルダ内にあるので、実行する
python examples/dht_simpleread.py実行すると以下の通り温度と湿度を返す。
DHT11, humidity 66.0%, temperature 23.0* DHT11, humidity 68.0%, temperature 21.0* DHT11, humidity 74.0%, temperature 21.0* DHT11, humidity 74.0%, temperature 21.0*余談
goで温度を測定するプログラムは以下のサイトを参考にする
https://github.com/d2r2/go-dhtexample1のサンプルコードで以下の修正を加えて
sensorType := dht.DHT11 pin := 12rootユーザで実行すれば温度・湿度測定ができる。
- 投稿日:2020-11-23T17:43:13+09:00
WebSocket のクライアント / サーバー CLI ツールを作った
表題どおりの wsnc という CLI ツールを作成しました。これ一つで WebSocket のクライアントとしてもサーバーとしても使えます。netcat (nc) コマンドの WebSocket 版みたいなイメージです。
- tomatod/wsnc: https://github.com/tomatod/wsnc
使用感
シンプルに使うとこんな感じです↓
サーバー側でブロードキャストさせることもできます↓
始め方
Go の開発環境をお持ちの方は go get からどうぞ↓
$ go get github.com/tomatod/wsnc $ wsnc -h ...一応実行ファイルを ZIP して配布しておりますので、よろしければ是非是非 (なお Mac は動作未検証、、、) ↓
https://github.com/tomatod/wsnc/releases/tag/0.8.0わからないとき
wsnc -h コマンドでヘルプが表示できます。あとは日本語のマニュアルも作りましたので是非 (差別化のつもり) ↓
https://github.com/tomatod/wsnc/blob/master/README_JP.md是非是非使ってください!
似ているツール
Rust 製のいいツールがあるようです↓ (くっ、、出来では負けている。しかもバイナリの小ささに嫉妬)
- vi/websocat: https://github.com/vi/websocat自己紹介
趣味グラマーです。時々ツール作るのでよろしくおねがいします!
なお次に作る予定のもの (乞うご期待):
- マルチプラットフォームで使える ARPING
- Proxy Protocol v1/v2 をキャプチャーするツール
- 投稿日:2020-11-23T17:43:13+09:00
WebSocket のクライアント / サーバー CLI ツールを作った (WebSocket 版 netcat 的な)
表題どおりの wsnc という CLI ツールを Go 言語で作成しました。これ一つで WebSocket のクライアントとしてもサーバーとしても使えます。netcat (nc) コマンドの WebSocket 版みたいなイメージです。
- tomatod/wsnc: https://github.com/tomatod/wsnc
英語の他に日本語のマニュアルも作りました↓
https://github.com/tomatod/wsnc/blob/master/README_JP.md使用感
シンプルに使うとこんな感じです (現在はもう少し見た目がシンプルになりました)↓
主に対応している機能 (RFC6455 に沿う)
- Text / Binary / Ping / Pong / Close メッセージに対応
- 任意の Close Code で Close メッセージを送信可能
- サーバー側のブロードキャスト機能
- クライアントの one-shot モード (1 メッセージのみ送信して終了するモード)
- WebSocket アップグレードリクエスト時の HTTP ヘッダを任意に編集
検証用途に便利だと思います。
始め方
Go の開発環境をお持ちの方は go get からどうぞ↓
$ go get github.com/tomatod/wsnc $ wsnc -h ...一応実行ファイルを ZIP して配布しておりますので、よろしければ是非是非 (なお Mac は動作未検証、、、) ↓
https://github.com/tomatod/wsnc/releases/tag/0.8.0似ているツール
Rust 製のいいツールがあるようです↓ (バイナリの小ささに嫉妬)
- vi/websocat: https://github.com/vi/websocat
- 投稿日:2020-11-23T16:51:06+09:00
GoでPostgreから取得したSelectクエリをJSONに変換する
やりたいこと
- SELECT文で取得したクエリをまるごとJSONにしたい
- sqlパッケージのscanで一行ずつ処理しているようで、ループの中で配列を作る必要がある(?)
- 配列からjsonパッケージで変換する
- 参考のコードはMSのサイトにのっているやつ
コード
main.gopackage main import ( "database/sql" "encoding/json" "fmt" _ "github.com/lib/pq" ) const ( // Initialize connection constants. HOST = "127.0.0.1" DATABASE = "testdb" USER = "root" PASSWORD = "password" ) func checkError(err error) { if err != nil { panic(err) } } func main() { // Initialize connection string. var connectionString string = fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable", HOST, USER, PASSWORD, DATABASE) // Initialize connection object. db, err := sql.Open("postgres", connectionString) checkError(err) err = db.Ping() checkError(err) fmt.Println("Successfully created connection to database") // Read rows from table. var id int var name string var quantity int sql_statement := "SELECT * from inventory;" rows, err := db.Query(sql_statement) checkError(err) defer rows.Close() // 構造を定義 type data struct { ID int Name string Quantity int } // 配列の型を宣言 var fruit []data for rows.Next() { switch err := rows.Scan(&id, &name, &quantity); err { case sql.ErrNoRows: fmt.Println("No rows were returned") case nil: fmt.Printf("Data row = (%d, %s, %d)\n", id, name, quantity) // 一行毎に配列を追加 fruit = append(fruit,data{ ID: id, Name: name, Quantity: quantity, }) default: checkError(err) } } fruitjson, _ := json.Marshal(fruit) fmt.Println(string(fruitjson)) }結果
yuta:~/postgre $ go run main.go Successfully created connection to database Data row = (1, banana, 150) Data row = (2, orange, 154) Data row = (3, apple, 100) Data row = (4, test, 100) [{"ID":1,"Name":"banana","Quantity":150},{"ID":2,"Name":"orange","Quantity":154},{"ID":3,"Name":"apple","Quantity":100},{"ID":4,"Name":"test","Quantity":100}]参考
https://docs.microsoft.com/ja-jp/azure/postgresql/connect-go
- 投稿日:2020-11-23T15:48:41+09:00
GitHub Releasesからインストールしたコマンドを管理するツールを作った
GitHub Releasesから取得したコマンドを所定のパスに配置して、
一括アップグレードできるようにするコマンドを作りました。なぜ作ったかと、仕組みについて書きます。
なぜ作ったか
インストールしたコマンドのアップグレードをするのが面倒だったのを解消したかったからです。
GitHub Releasesから取得するタイプのコマンドをインストールする時、僕は以下のようなコマンドを実行します。
cd /tmp wget https://github.com/jiro4989/nimjson/releases/download/v1.2.8/nimjson_linux.tar.gz tar xzf nimjson_linux.tar.gz mkdir -p ~/bin install -m 0755 ./nimjson_linux/bin/nimjson ~/bin/インストールする時は特にこれで不便ありません。
ですが、コマンドをアップグレードしたくなった時に困りました。主に以下の問題に遭遇しました。
- このコマンドどこから取得したっけ?
- どうやってインストールしたっけ?
- そもそも新しいバージョン出てるんだっけ?
この問題はGitHub Releasesから取得するコマンドが増えるほど大きくなりました
ソースコード
前述の問題を解消するために
relma
というコマンドを作りました。https://github.com/jiro4989/relma
Windowsでも動作します(管理者権限が必要ですが)。
使い方
インストール方法
最初に
init
で初期化して、install
にリリース物のURLを渡してあげるだけです。これでリリース物の圧縮ファイルを展開して
$HOME/relma/bin
に実行可能ファイルのシンボリックリンクが配置されます。relma init relma install https://github.com/jiro4989/nimjson/releases/download/v1.2.8/nimjson_linux.tar.gz
アップグレード方法
以下の様に
update
してupgrade
するだけです。
update
では最新バージョンの有無をチェックし、バージョン情報をローカルに保存します。
upgrade
を実行するとアップグレード可能なパッケージをすべてアップグレードします。relma update relma upgradeインストールしたパッケージの確認方法
relma でインストールしたパッケージの一覧を確認する場合は
list
を実行します。relma list仕組み
インストール方法
relma install
に渡したURLのファイルをローカルに落し、所定のパスに展開してシンボリックリンクを作ります。$HOME/ relma/ bin/ command.exe # シンボリックリンク releases/ $OWNER/ $REPO/ $VERSION/ $RELEASE_FILE.tar.gz assets/ command.exe # 実体リリースファイルの展開後のディレクトリ構造にはある程度パターンがあります。
大体は以下の 3 パターンのいずれかだろう、と考えました。
これらの展開後のディレクトリ構造を判別して実行可能ファイルのパスを特定し、
$HOME/relma/bin
配下にシンボリックリンクを作成します。release_v1.0.0.zip/ command.exe # コマンドだけ配置されるケース release_v1.0.0.zip/ release_v1.0.0/ command.exe # 圧縮ファイル名のディレクトリ配下に # コマンドが配置されるケース release_v1.0.0.zip/ release_v1.0.0/ bin/ command.exe # 圧縮ファイル名のディレクトリ配下に # bin ディレクトリが配置され、 # その下にコマンドが配置されるケースアップグレード時のインストールURLの特定方法
GitHub Releasesで公開されているコマンドの多くは、リリース手順を自動化されています。
ローカルで手動で叩くコマンドか、あるいはCIからか、手段は違えど大なり小なり自動化されている場合が多いです。
また、リリースファイルの命名も、リポジトリごとに違えど、概ね命名が決まっていて、「リリースファイル名に含まれるバージョン番号だけが異なる」という点で共通点があります。
よって、
relma install
に指定したURLのバージョン番号をリリースのタグ番号で差し替えれば、次のバージョンのリリースファイルを取得するURLが特定できるのでは、と考えました。https://github.com/jiro4989/nimjson/releases/download/${VERSION}/nimjson_${VERSION}_linux.tar.gzしかし、開発者が毎回手動でリリースファイルを作っていて、命名が不規則だったり、タグとバージョン番号が不一致になるケースもあると思います
これはサポート外としました。
あらゆるリポジトリをサポートするつもりはないですし、命名が不規則なのはリポジトリのオーナーの管理の問題と考えます。
まとめ
- relma コマンドの使い方を説明しました
- relma コマンドの仕組みを説明しました
コマンド管理に立てば幸いです。
以上
- 投稿日:2020-11-23T15:09:57+09:00
GO環境でimport Cエラー
エラー発生
Goのgraphqlライブラリの
gqlgen
でスキーマを更新しようとしたら謎のエラー/go/src # go run github.com/99designs/gqlgen validation failed: packages.Load: /usr/local/go/src/net/cgo_linux.go:12:8: could not import C (no metadata for C) exit status 1解決
どうやらgccがdockerイメージ上に入ってない模様。
apk update
してapkをアップデートした後、alpine-sdk
というビルドパッケージ?を入れたらうまく行きました。
apkについては、この記事が分かりやすかったです。/go/src # apk update fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz v3.12.1-44-g754f23ac8f [http://dl-cdn.alpinelinux.org/alpine/v3.12/main] v3.12.1-41-g42f619918d [http://dl-cdn.alpinelinux.org/alpine/v3.12/community] OK: 12746 distinct packages available/go/src # apk add alpine-sdk (1/37) Upgrading musl (1.1.24-r9 -> 1.1.24-r10) 0% (2/37) Installing fakeroot (1.24-r0) (3/37) Installing openssl (1.1.1g-r0) (4/37) Installing libattr (2.4.48-r0) (5/37) Installing attr (2.4.48-r0) (6/37) Installing libacl (2.2.53-r0) (7/37) Installing tar (1.32-r1) (8/37) Installing pkgconf (1.7.2-r0) (9/37) Installing patch (2.7.6-r6) (10/37) Installing libgcc (9.3.0-r2) (11/37) Installing libstdc++ (9.3.0-r2) (12/37) Installing lzip (1.21-r0) (13/37) Installing nghttp2-libs (1.41.0-r0) (14/37) Installing libcurl (7.69.1-r1) (15/37) Installing curl (7.69.1-r1) (16/37) Installing abuild (3.6.0-r1) Executing abuild-3.6.0-r1.pre-install (17/37) Installing binutils (2.34-r1) (18/37) Installing libmagic (5.38-r0) (19/37) Installing file (5.38-r0) (20/37) Installing gmp (6.2.0-r0) (21/37) Installing isl (0.18-r0) (22/37) Installing libgomp (9.3.0-r2) (23/37) Installing libatomic (9.3.0-r2) (24/37) Installing libgphobos (9.3.0-r2) (25/37) Installing mpfr4 (4.0.2-r4) (26/37) Installing mpc1 (1.1.0-r1) (27/37) Installing gcc (9.3.0-r2) (28/37) Installing musl-dev (1.1.24-r10) (29/37) Installing libc-dev (0.7.2-r3) (30/37) Installing g++ (9.3.0-r2) (31/37) Installing make (4.3-r0) (32/37) Installing fortify-headers (1.1-r0) (33/37) Installing build-base (0.5-r2) (34/37) Installing expat (2.2.9-r1) (35/37) Installing pcre2 (10.35-r0) (36/37) Installing git (2.26.2-r0) (37/37) Installing alpine-sdk (1.0-r0) Executing busybox-1.31.1-r19.trigger OK: 224 MiB in 51 packagesひとりごと
使っているdockerイメージ
golang:1.15.5-alpine3.12
がいけなかったのか。。
詳しい方教えてください>_<
- 投稿日:2020-11-23T15:09:57+09:00
GO環境でcould not import Cエラー
エラー発生
Goのgraphqlライブラリの
gqlgen
でスキーマを更新しようとしたら謎のエラー/go/src # go run github.com/99designs/gqlgen validation failed: packages.Load: /usr/local/go/src/net/cgo_linux.go:12:8: could not import C (no metadata for C) exit status 1解決
どうやらgccがdockerイメージ上に入ってない模様。
たぶんきっとこれ? https://github.com/golangci/golangci-lint/issues/602
apk update
してapkをアップデートした後、alpine-sdk
というビルドパッケージ?を入れたらうまく行きました。
apkについては、この記事が分かりやすかったです。/go/src # apk update fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz v3.12.1-44-g754f23ac8f [http://dl-cdn.alpinelinux.org/alpine/v3.12/main] v3.12.1-41-g42f619918d [http://dl-cdn.alpinelinux.org/alpine/v3.12/community] OK: 12746 distinct packages available/go/src # apk add alpine-sdk (1/37) Upgrading musl (1.1.24-r9 -> 1.1.24-r10) 0% (2/37) Installing fakeroot (1.24-r0) (3/37) Installing openssl (1.1.1g-r0) (4/37) Installing libattr (2.4.48-r0) (5/37) Installing attr (2.4.48-r0) (6/37) Installing libacl (2.2.53-r0) (7/37) Installing tar (1.32-r1) (8/37) Installing pkgconf (1.7.2-r0) (9/37) Installing patch (2.7.6-r6) (10/37) Installing libgcc (9.3.0-r2) (11/37) Installing libstdc++ (9.3.0-r2) (12/37) Installing lzip (1.21-r0) (13/37) Installing nghttp2-libs (1.41.0-r0) (14/37) Installing libcurl (7.69.1-r1) (15/37) Installing curl (7.69.1-r1) (16/37) Installing abuild (3.6.0-r1) Executing abuild-3.6.0-r1.pre-install (17/37) Installing binutils (2.34-r1) (18/37) Installing libmagic (5.38-r0) (19/37) Installing file (5.38-r0) (20/37) Installing gmp (6.2.0-r0) (21/37) Installing isl (0.18-r0) (22/37) Installing libgomp (9.3.0-r2) (23/37) Installing libatomic (9.3.0-r2) (24/37) Installing libgphobos (9.3.0-r2) (25/37) Installing mpfr4 (4.0.2-r4) (26/37) Installing mpc1 (1.1.0-r1) (27/37) Installing gcc (9.3.0-r2) (28/37) Installing musl-dev (1.1.24-r10) (29/37) Installing libc-dev (0.7.2-r3) (30/37) Installing g++ (9.3.0-r2) (31/37) Installing make (4.3-r0) (32/37) Installing fortify-headers (1.1-r0) (33/37) Installing build-base (0.5-r2) (34/37) Installing expat (2.2.9-r1) (35/37) Installing pcre2 (10.35-r0) (36/37) Installing git (2.26.2-r0) (37/37) Installing alpine-sdk (1.0-r0) Executing busybox-1.31.1-r19.trigger OK: 224 MiB in 51 packagesひとりごと
使っているdockerイメージ
golang:1.15.5-alpine3.12
がいけなかったのか。。
詳しい方教えてください>_<
- 投稿日:2020-11-23T13:37:25+09:00
[GO言語] YAMLファイルを読み込んでみよう
YAMLとは
環境
- CentOS 8.2
- go version 1.15.3 linux/amd64
準備
# go get gopkg.in/yaml.v2 # vi test.ymltest.ymlfirst: test secound: a1: count1 a2: - count2 - count3 a3: b1: count4YAMLファイルを読み込む
# vi main.go
main.gopackage main import( "fmt" "io/ioutil" "strconv" "gopkg.in/yaml.v2" ) func main() { // test.ymlを読み込む buf, err := ioutil.ReadFile("test.yml") if err != nil { fmt.Print("error: Failed to read the file\n") return } // 読み込んだファイルを map[interface {}]interface {}にマッピングする t := make(map[interface {}]interface {}) err = yaml.Unmarshal(buf, &t) if err != nil { panic(err) } fmt.Print(t["first"]) // test fmt.Print("\n") // t["secound"]を(map[interface {}]interface {})で型変換 fmt.Print(t["secound"].(map[interface {}]interface {})["a1"]) //count1 fmt.Print("\n") // len() 配列の要素数を返す fmt.Print(len(t["secound"].(map[interface {}]interface {}))) fmt.Print("\n") // []interface {}型の配列 fmt.Print(t["secound"].(map[interface {}]interface {})["a2"].([]interface {})[0]) // count2 fmt.Print("\n") fmt.Print(t["secound"].(map[interface {}]interface {})["a3"].(map[interface {}]interface {})["b1"]) // count4 fmt.Print("\n") // 規則的に命名されていれば、いくつあるか確認できる flag, i := 0, 0 for flag == 0 { i++ switch t["secound"].(map[interface {}]interface {})["a"+strconv.Itoa(i)].(type) { case nil: flag = 1 } } fmt.Printf("a%d is not found\n", i) // a4 is not found }# go run main.go test count1 3 count2 count4 a4 is not found参考文献
- 投稿日:2020-11-23T00:06:21+09:00
AtCoder Beginner Contest 184のメモ
前置き
Atcoderをやってみたので、自分用のメモです。
あとから加筆・修正する予定です。問題
https://atcoder.jp/contests/abc184
A
Q_A.gopackage main import ( "fmt" ) func main() { var a, b, c, d int fmt.Scanf("%d %d", &a, &b) fmt.Scanf("%d %d", &c, &d) ans := a * d - b * c fmt.Printf("%d\n", ans) }B
Q_B.gopackage main import ( "fmt" "strings" ) func main() { var N, X int fmt.Scanf("%d %d", &N, &X) var S string fmt.Scanf("%s", &S) result := strings.Split(S, "") for i:=0; i<N; i++{ if result[i] == "o"{ X += 1 } else if X > 0{ X -= 1 } } fmt.Printf("%d\n", X) }C
Q_C.gopackage main import ( "fmt" "math" ) func main() { var r1, r2, c1, c2 int fmt.Scanf("%d %d", &r1, &c1) fmt.Scanf("%d %d", &r2, &c2) var ans int if (r1 == r2) && (c1 == c2){ ans = 0 } else if (r1+c1 == r2+c2) || (r1-c1 == r2-c2) || math.Abs(float64(r1-r2)) + math.Abs(float64(c1-c2)) <=3{ ans = 1 } else if ((r2 - r1 + c2 - c1) % 2 == 0) || (math.Abs(float64(r2 - r1 - c2 + c1)) <= 3) || (math.Abs(float64(r2 - r1 + c2 - c1)) <= 3){ ans = 2 } else { ans = 3 } fmt.Printf("%d\n", ans) }D
Q_D.gopackage main import ( "fmt" ) var dp [101][101][101]float64 // 移動の期待値を返す再帰関数 func f(a int, b int, c int) float64{ // すでに計算していたら if dp[a][b][c] != 0{ return dp[a][b][c] } // ゴールしていたら移動の期待値は0 if (a == 100) || (b == 100) || (c == 100) { return 0 } var ans float64 = 0 ans += (f(a+1, b, c) + 1) * float64(a) / float64(a + b + c) ans += (f(a, b+1, c) + 1) * float64(b) / float64(a + b + c) ans += (f(a, b, c+1) + 1) * float64(c) / float64(a + b + c) dp[a][b][c] = ans return ans } func main() { var A, B, C int fmt.Scanf("%d %d %d", &A, &B, &C) fmt.Printf("%f\n", f(A, B, C)) }E
覚えてたら後で書きます。
F
覚えてたら後で書きます。