Rustのhelloworldを試す。
インストール
curl https://sh.rustup.rs -sSf | sh
環境設定
source $HOME/.cargo/env
でOK
確認
$ rustc --version rustc 1.37.0 (eae3437df 2019-08-13)
まずはHelo worldのみ
main.rs
fn main() { println!("hello, world"); }
ついでに超簡単なfizzbuzzも
fn main() { for num in 1..51 { let mut _str = ""; if num % 3 == 0 && num % 5 != 0{ _str = "fizz"; } else if num % 3 != 0 && num % 5 == 0 { _str = "buzz"; } else if num % 3 == 0 && num % 5 == 0{ _str = "fizzbuzz" } println!("{}:{}", num, _str); } }
所感
まだ、触ったばかりでわからない状況
メモリ管理もいろいろできるみたいだし、文法の学習をしながら他の言語との比較を行っていく
javascriptのPromiseとasync / awaitについて少し試す
Promiseは
並列処理でちょっと前に学習したやつで
function sampleTask1() { return new Promise(function(resolve, reject) { setTimeout(function () { console.log('sample1'); resolve("sample1"); }, 3000); }); }
って定義したら
↓
sampleTask1() .then(function(result) { console.log("result", result); }) .catch(function(error) { console.log("error"); });
で実行した際に非同期で動作して、正常時にはresolve、異常時にはrejectで返却するやつです。
今回は?
async / awaitがある
これは
非同期処理をもう少しスッキリ書けるらしい
まずは今までのやつ
console.log("start"); Promise.resolve() .then(function() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-1"); resolve("sample2-1"); }, 16); }); }) .then(function(result) { console.log("result", result); }) .then(function() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-2"); resolve("sample2-2"); }, 10); }) }) .then(function(result) { console.log("result", result); }) .then(function() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-3"); resolve("sample2-3"); }, 5); }); }) .then(function(result) { console.log("result", result); }); console.log("end");
これが
↓
// まず、Promiseを返す関数を定義 function taskA() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-1"); resolve("sample2-1"); }, 16); }) } function taskB() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-2"); resolve("sample2-2"); }, 25); }) } function taskC() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-3"); resolve("sample2-3"); }, 5); }) } // 逐次処理を行うやつ async function taskSample1() { // 1つずつ実行 const res1 = await taskA(); console.log("res1:", res1); const res2 = await taskB(); console.log("res2:", res2); const res3 = await taskC(); console.log("res3;", res3); // 配列に設定して順次実行 const taskList = [ taskA, taskB, taskC ]; for (let i=0;i<taskList.length;i++) { const res = await taskList[i](); console.log(`res${i}=`, res); } } // 実行 console.log("start"); taskSample1(); console.log("end");
こうなる
「async」を定義した関数はPromiseを返すようになるらしい、
また「await」は処理結果を返すまで待機してくれるとのこと
基本的には両方セットで使うみたい。
fetchを使う場合は
async function getRequest() { const response = await fetch("http://127.0.0.1:8080/sample_api1", { method: "POST", // *GET, POST, PUT, DELETE, etc. mode: "cors", // no-cors, cors, *same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, same-origin, *omit headers: { "Content-Type": "application/json; charset=utf-8" }, redirect: "follow", // manual, *follow, error referrer: "no-referrer", // no-referrer, *client //body: JSON.stringify("{}"), // 本文のデータ型は "Content-Type" ヘッダーと一致する必要があります }); const data = await response.json(); console.log(data); } console.log("start"); for (let i=0;i<5;i++) { getRequest(); } console.log("end");
うん、なんとなく同期処理っぽくかけるのが良い感じですね(^o^)
今回は記載しませんがPromise.allで複数の並列処理後の結果を取得してごにょごにょとかいうのもやってみよう
所感
結構スッキリかけるようになったようになっています。
ただ、Promiseの仕組みを十分に理解することやエラーの箇所の記載がないようにエラーに関する挙動をどうするかを今後検討していきたい。
javascriptのfetchを使ってAPIより結果を取得
概要
fetch使ってみたい
APIはgo言語で作成した適当なやつ
サーバ側
package main import ( "encoding/json" "log" "math/rand" "net/http" "time" ) func main() { http.HandleFunc("/sample_api1", sampleAPI1) http.HandleFunc("/sample_api2", sampleAPI2) http.HandleFunc("/sample_api3", sampleAPI3) http.ListenAndServe("127.0.0.1:8080", nil) } // Response ... type Response struct { Status int `json:"status"` Rssult string `json:"result"` } func sampleAPI1(w http.ResponseWriter, r *http.Request) { //if r.Method == http.MethodOptions { // return //} log.Println("api1", r.Method) rand.Seed(time.Now().UnixNano()) time.Sleep(time.Duration(int(rand.Intn(5))) * time.Second) response := Response{http.StatusOK, "ok1"} res, _ := json.Marshal(response) r.Close = true defer r.Body.Close() w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "*") w.Header().Set("Accept", "application/json") w.Header().Set("Content-Type", "application/json") w.Write(res) } func sampleAPI2(w http.ResponseWriter, r *http.Request) { //if r.Method == http.MethodOptions { // return //} log.Println("api2", r.Method) rand.Seed(time.Now().UnixNano()) time.Sleep(time.Duration(int(rand.Intn(5))) * time.Second) response := Response{http.StatusOK, "ok2"} res, _ := json.Marshal(response) w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "*") w.Header().Set("Content-Type", "application/json") w.Write(res) } func sampleAPI3(w http.ResponseWriter, r *http.Request) { //if r.Method == http.MethodOptions { // return //} log.Println("api3", r.Method) rand.Seed(time.Now().UnixNano()) time.Sleep(time.Duration(int(rand.Intn(5))) * time.Second) response := Response{http.StatusOK, "ok3"} res, _ := json.Marshal(response) w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "*") w.Header().Set("Content-Type", "application/json") w.Write(res) }
やって置かないとポートが違うとかなんとかでCORSエラーで弾かれる
javascript(Promise.all)
unction taskA() { return fetch("http://127.0.0.1:8080/sample_api1", { method: "GET", // *GET, POST, PUT, DELETE, etc. mode: "cors", // no-cors, cors, *same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, same-origin, *omit headers: { "Content-Type": "application/json; charset=utf-8", }, redirect: "manual", // manual, *follow, error referrer: "no-referrer", // no-referrer, *client //body: JSON.stringify("{}"), // 本文のデータ型は "Content-Type" ヘッダーと一致する必要があります }) .then(function(response) { console.log("taskA"); return response.json(); }); } function taskB() { return fetch("http://127.0.0.1:8080/sample_api2", { method: "GET", // *GET, POST, PUT, DELETE, etc. mode: "cors", // no-cors, cors, *same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, same-origin, *omit headers: { "Content-Type": "application/json; charset=utf-8", }, redirect: "manual", // manual, *follow, error referrer: "no-referrer", // no-referrer, *client //body: JSON.stringify("{}"), // 本文のデータ型は "Content-Type" ヘッダーと一致する必要があります }) .then(function(response) { console.log("taskB"); return response.json(); }); } function taskC() { return fetch("http://127.0.0.1:8080/sample_api3", { method: "GET", // *GET, POST, PUT, DELETE, etc. mode: "cors", // no-cors, cors, *same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, same-origin, *omit headers: { "Content-Type": "application/json; charset=utf-8", }, redirect: "manual", // manual, *follow, error referrer: "no-referrer", // no-referrer, *client //body: JSON.stringify("{}"), // 本文のデータ型は "Content-Type" ヘッダーと一致する必要があります }) .then(function(response) { console.log("taskC"); return response.json(); }); } // 並列ですべて完了後にレスポンスを返却 console.log("start"); Promise.all([ taskA(), taskB(), taskC() ]).then(function(data) { console.log("result start"); console.log(data); console.log("result end"); }); console.log("end");
↓
start end taskB taskC taskA result start (3) [{…}, {…}, {…}]0: {status: 200, result: "ok1"}1: {status: 200, result: "ok2"}2: {status: 200, result: "ok3"}length: 3__proto__: Array(0) result end
※逐次処理も同じ感じで対応できそう
所感
今までajaxのcallbackでやってた部分が多いため、Promiseに対応していかないといけないが
ちょっと仕組みが難しく感じる
少しずつ確認して理解していくしかない…
javascriptのPromiseとかいうのを今更少しだけ学習する
Promise
非同期処理するやつ
Promiseで実行した結果はresolveが正常時、rejectが異常時に設定しないと取得できないらしい
サンプル
1つの処理についての非同期処理
unction sampleTask1() { return new Promise(function(resolve, reject) { setTimeout(function () { console.log('sample1'); resolve("sample1"); }, 3000); }); } console.log("start"); sampleTask1() .then(function(result) { console.log("result", result); }) .catch(function(error) { console.log("error"); }); console.log("end");
↓
start end sample1 result sample1
※単純に「new Promise」のオブジェクトより結果を判定する
複数の処理を非同期内で逐次処理で行う
console.log("start"); Promise.resolve() .then(function() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-1"); resolve("sample2-1"); }, 16); }); }) .then(function(result) { console.log("result", result); }) .then(function() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-2"); resolve("sample2-2"); }, 10); }) }) .then(function(result) { console.log("result", result); }) .then(function() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-3"); resolve("sample2-3"); }, 5); }); }) .then(function(result) { console.log("result", result); }); console.log("end");
↓
start end sample2-1 result sample2-1 sample2-2 result sample2-2 sample2-3 result sample2-3
順番に処理を行うため、1つ前の実行結果を次の処理で取得するようになっていて、最後に一括で取得などを行いたい場合は少し工夫する必要がある。
複数の処理を実行し、全ての処理が完了後に結果を取得
console.log("start"); Promise.all([ new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-1"); resolve("sample2-1"); }, 16); }) , new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-2"); resolve("sample2-2"); }, 10); }) , new Promise(function(resolve, reject) { setTimeout(function() { console.log("sample2-3"); resolve("sample2-3"); }, 25); }) ]).then(function(data) { console.log("result start"); console.log(data); console.log("result end"); }); console.log("end"); |< ↓ >|| start end sample2-2 sample2-1 sample2-3 result start (3) ["sample2-1", "sample2-2", "sample2-3"]0: "sample2-1"1: "sample2-2"2: "sample2-3"length: 3__proto__: Array(0) result end
すべての処理が並列で動作し、最後に処理を実行するため、最後に取得するまでは値を取得できない
まあ、なんか方法はあるとは思うが…
所感
allによる同時並列と逐次処理で次の処理へ流せるのは少しだけ理解した
次はfetchを利用した手法で見てみる
golangのpanic発生しても処理を続行したい
golangでのエラーとかって
基本的にはエラーオブジェクトのチェックしかしていない
panic発生したら
落ちます
package main import ( "log" ) func main() { log.Println("start") // 意図的にpanicを起こす panic("aaaa") //var a *interface{} //*a = 0 //x := 10 //y := 0 //b := x / y //log.Println(b) log.Println("end") }
↓
2019/08/14 10:04:05 start panic: aaaa goroutine 1 [running]: main.main() /sample2-b.go:12 +0x79 exit status 2
そうならないようにerrオブジェクトや変数のチェックで抑制していますが
まれになんらかの理由でオブジェクトにnullが挿入される自体が発生してpanicがおきたらマズい
javaのtry-catchとかあればよいがそういうのはないため、
deferとrecoverを併用することで対応できるとのこと
ドキュメントより以下、引用(http://golang.jp/effective_go#recover)
panicが呼び出されたとき(これには、配列のインデックスが範囲外であるときや、型アサーションに失敗したような暗黙的なものも含む)は、すぐさま、カレントの関数を停止し、ゴルーチンのスタックの巻き戻しを開始します。その途中、遅延指定されている関数をすべて実行します。この巻き戻しがゴルーチンのスタックの先頭にたどり着くと、プログラムは終了します。ただし、組み込み関数recoverを使うことで、ゴルーチンの制御を取り戻し、通常の実行を再開させることが可能です。
書き直し
package main import ( "log" "fmt" "runtime" ) func main() { log.Println("start") // 今回は即時関数にしているがerrorの戻り値を取得できるならなんでもよい err := func() (errRes error) { // panic発生時に補足するやつ defer func() { if err := recover(); err != nil { // エラー情報を戻り値のerrResへ設定 errRes = fmt.Errorf("error: %s", err) // stack trace for i:=0;;i++ { _, file, line, ok := runtime.Caller(i) if ok == false { break } log.Printf("depth: %d, line: %4d, file:%v\n", i, line, file) } } }() // 意図的にpanicを起こす //panic("aaaa") //var a *interface{} //*a = 0 x := 10 y := 0 b := x / y log.Println(b) // ここまできたら正常 return nil }() // errorチェック if err != nil { log.Println(err) } log.Println("end") }
↓
2019/08/14 10:13:38 start 2019/08/14 10:13:38 depth: 0, line: 22, file: /work/golang/sample2.go 2019/08/14 10:13:38 depth: 1, line: 522, file:/usr/local/Cellar/go/1.12.7/libexec/src/runtime/panic.go 2019/08/14 10:13:38 depth: 2, line: 61, file:/usr/local/Cellar/go/1.12.7/libexec/src/runtime/panic.go 2019/08/14 10:13:38 depth: 3, line: 37, file:/work/golang/sample2.go 2019/08/14 10:13:38 depth: 4, line: 42, file:/work/golang/sample2.go 2019/08/14 10:13:38 depth: 5, line: 200, file:/usr/local/Cellar/go/1.12.7/libexec/src/runtime/proc.go 2019/08/14 10:13:38 depth: 6, line: 1337, file:/usr/local/Cellar/go/1.12.7/libexec/src/runtime/asm_amd64.s 2019/08/14 10:13:38 error: runtime error: integer divide by zero 2019/08/14 10:13:38 end
Webフレームワークとかは
API配下のpanicは拾ってくれるが、内部でgoroutineなどを任意で定義した場合にpanicを起こすと
Webフレームワークのアプリ自体が停止する可能性がある・・・
参考
Go言語のエラーハンドリングについて ~panic編~ - Qiita
golangでrecoverしたときの戻り値 - Qiita
http://golang.jp/effective_go#recover
golangでpanicをrecoverしたときにスタックトレースを表示する - code.alone
所感
なんかスマートじゃない感じ…
現状、これしか見つからないからこの方法で対応を試みます。
golangでUUIDの生成をライブラリでお試し
仕事でコード書くより
設計の仕事ばっかり、スケジュール管理とかめんどくさいので
他の人やってくんないかな…
UUIDって?
UUID(Universally Unique Identifier)とは、ソフトウェア上でオブジェクトを一意に識別するための識別子である。
ざっくりいうとユニークIDみたいやつ
基本的にはsha1とかmd5とか乱数で生成していたけど
そういったものにフォーマットがついた感じ
例:3cc807ab-8e31-3071-aee4-f8f03781cb91
バージョン
現在1から5までの方法がある
確認用ライブラリ
https://github.com/google/uuid
今度改めて自身でアルゴリズムは検討するが今回はちょっとお試しでやってみる
ソース
package main import ( "github.com/google/uuid" "fmt" ) func main() { fmt.Println("version1 NewUUID --") for i:=0;i<10;i++ { uuidObj, _ := uuid.NewUUID() fmt.Println(" ", uuidObj.String()) } fmt.Println("version2 NewDCESecurity --") for i:=0;i<10;i++ { uuidObj, _ := uuid.NewUUID() domain := uuidObj.Domain() id := uuidObj.ID() uuidObj2, _ := uuid.NewDCESecurity(domain, id) fmt.Println(" ", uuidObj2.String()) } fmt.Println("version3 NewMD5 --") for i:=0;i<10;i++ { uuidObj, _ := uuid.NewUUID() data := []byte("wnw8olzvmjp0x6j7ur8vafs4jltjabi0") uuidObj2 := uuid.NewMD5(uuidObj, data) fmt.Println(" ", uuidObj2.String()) } fmt.Println("version5 NewSHA1 --") for i:=0;i<10;i++ { uuidObj, _ := uuid.NewUUID() data := []byte("wnw8olzvmjp0x6j7ur8vafs4jltjabi0") uuidObj2 := uuid.NewSHA1(uuidObj, data) fmt.Println(" ", uuidObj2.String()) } fmt.Println("version4 NewRandom --") for i:=0;i<10;i++ { uuidObj, _ := uuid.NewRandom() fmt.Println(" ", uuidObj.String()) } }
結果
mshige1979MBA:golang matsumotoshigeharu$ go run sample1.go version1 NewUUID -- ef45b54c-9f70-11e9-a730-6476baad914e ef45c294-9f70-11e9-a730-6476baad914e ef45c2b2-9f70-11e9-a730-6476baad914e ef45c2c6-9f70-11e9-a730-6476baad914e ef45c2e4-9f70-11e9-a730-6476baad914e ef45c2f8-9f70-11e9-a730-6476baad914e ef45c316-9f70-11e9-a730-6476baad914e ef45c334-9f70-11e9-a730-6476baad914e ef45c352-9f70-11e9-a730-6476baad914e ef45c366-9f70-11e9-a730-6476baad914e version2 NewDCESecurity -- ef45c38e-9f70-21e9-a730-6476baad914e ef45c3ac-9f70-21e9-a730-6476baad914e ef45c3ca-9f70-21e9-a731-6476baad914e ef45c3e8-9f70-21e9-a732-6476baad914e ef45c410-9f70-21e9-a732-6476baad914e ef45c442-9f70-21e9-a732-6476baad914e ef45c46a-9f70-21e9-a733-6476baad914e ef45c49c-9f70-21e9-a733-6476baad914e ef45c4c4-9f70-21e9-a734-6476baad914e ef45c4ec-9f70-21e9-a735-6476baad914e version3 NewMD5 -- 3cc807ab-8e31-3071-aee4-f8f03781cb91 7e7e001e-6957-38d5-b035-41926dd035dd 91d52425-9470-3e2b-8e5f-649b7b4ec795 157ffb9e-d6b2-3b99-9fca-1d347f60b3e3 33b0480d-6d5f-358a-a37a-893e5850fa62 4b41d96b-dd72-3314-9cc2-1ab241eacb30 9337ce23-6909-3137-98d2-a9372bf57692 1e15f3d0-a040-3eca-a8bc-c677bc8bc619 b90f3b5d-059c-3c0e-b3d8-85c577763bf6 f741b68d-a9d2-3396-b499-745920a718ff version5 NewSHA1 -- 13f575fa-02d7-5c38-8e66-48524dd233a4 a56079b2-5373-5656-911a-483e3a92f19c 18c2d54b-1a94-5928-8a4a-2f3dd5fc3e57 8ac4f8a2-89b8-5ea3-81eb-d1654deaab51 bb6bff8b-615f-5791-a9fb-e3543fd9d02e 8209f28f-ccc9-5a90-beaf-d7e8e9927183 387ab566-8b80-5c6c-a156-8e49a5c9c3fe 75a4de2d-8049-5bb1-80c9-7250959af3d2 5991cc2e-2bac-5f83-9ae0-b4a45882a11a b8e33f96-449d-5972-8c9c-98b0487549dd version4 NewRandom -- 01a2c8b4-e3ec-4df5-a027-b7ffe5c6ed5d eb2aa249-3614-4833-b979-99c87c4189a8 4c8bda02-4b27-460a-b46f-d65b4e4f5e48 23df6b4c-e10f-4bcd-b935-0224f3216680 2ab1a839-08b2-4069-9bd7-a772c5934e66 dab1ade8-a446-4609-844b-257a7ab1ba0b eb770f37-a59a-4888-9789-d585f514ae93 b9999fdb-cd20-4bdb-b671-6228667a6746 8160d492-1ead-4d33-b4e8-d242cf2df332 63b96ec6-e9d7-4fa4-abb7-31b9e12fca0d