m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

自己CA認証局を作成して、SSLページを表示する

chromeとか

もう、オレオレ証明書だけでは見せてくれなくなった(´・ω・`)

CAとかわからないけど

ネットで検索していくつか出たものを参考に作成してみた

準備

opensslの設定ファイルをコピー
mkdir -p /etc/pki/caCrt
cp -p /etc/pki/tls/openssl.cnf /etc/pki/caCrt/.
cp -p /etc/pki/tls/openssl.cnf /etc/pki/caCrt/openssl-ca.cnf
cp -p /etc/pki/tls/openssl.cnf /etc/pki/caCrt/openssl-server.cnf
cp -p /etc/pki/tls/openssl.cnf /etc/pki/caCrt/openssl-client.cnf
CA用の編集(一部追加)
vi /etc/pki/caCrt/openssl-ca.cnf
----
[ usr_cert ]
basicConstraints=CA:TRUE
nsCertType = client, email
subjectAltName=@alt_names
----
サーバ証明書用の編集(一部追加)
vi /etc/pki/caCrt/openssl-server.cnf
----
[ usr_cert ]
basicConstraints = CA:FALSE
nsCertType =  server
subjectAltName=@alt_names
----
クライアント証明書用の編集(一部追加)
vi /etc/pki/caCrt/openssl-client.cnf
----
[ usr_cert ]
basicConstraints=CA:FALSE
nsCertType =  client, email, objsign
----
DNS設定
vi /etc/pki/caCrt/san.txt
----
subjectAltName=DNS:sample.com,DNS:*.sample.com
----

CA(自己認証局)作成

秘密鍵作成
openssl genrsa \
    -aes256 \
    -out cakey.pem 2048
> Enter pass phrase for cakey.pem: [秘密鍵のパスワード]
> Verifying - Enter pass phrase for cakey.pem: [秘密鍵のパスワード]
CSRファイル生成
openssl req -new \
    -config /etc/pki/caCrt/openssl-ca.cnf \
    -key cakey.pem \
    -out cacert.csr
> Enter pass phrase for cakey.pem: [秘密鍵のパスワード]
> You are about to be asked to enter information that will be incorporated
> into your certificate request.
> What you are about to enter is what is called a Distinguished Name or a DN.
> There are quite a few fields but you can leave some blank
> For some fields there will be a default value,
> If you enter '.', the field will be left blank.
> -----
> Country Name (2 letter code) [XX]:JP  ← なんか適当に
> State or Province Name (full name) []:Fukuoka ← なんか適当に
> Locality Name (eg, city) [Default City]:Fukuoka ← なんか適当に
> Organization Name (eg, company) [Default Company Ltd]:OreOre inc. ← なんか適当に
> Organizational Unit Name (eg, section) []: ← ← なんか適当に
> Common Name (eg, your name or your server's hostname) []:localhost ← なんか適当に
> Email Address []:  ← ブランク
> 
> Please enter the following 'extra' attributes
> to be sent with your certificate request
> A challenge password []: ← ブランク
> An optional company name []: ← ブランク
CA証明書作成
openssl x509 \
    -days 3650 \
    -in cacert.csr \
    -req -signkey cakey.pem \
    -out cacert.pem
> Signature ok
> subject=/C=JP/ST=Fukuoka/L=Fukuoka/O=OreOre inc./CN=localhost
> Getting Private key
> Enter pass phrase for cakey.pem: [秘密鍵のパスワード]
認証局管理用のファイルを初期化
touch /etc/pki/CA/index.txt
echo 00 > /etc/pki/CA/serial

サーバ証明書

秘密鍵を作成
openssl genrsa -aes256 -out privkey.pem 2048
> Enter pass phrase for privkey.pem:
> Verifying - Enter pass phrase for privkey.pem:
CSR作成
openssl req \
    -new -key privkey.pem \
    -out domain_name.csr
> Enter pass phrase for privkey.pem: [password]
> You are about to be asked to enter information that will be incorporated
> into your certificate request.
> What you are about to enter is what is called a Distinguished Name or a DN.
> There are quite a few fields but you can leave some blank
> For some fields there will be a default value,
> If you enter '.', the field will be left blank.
> -----
> Country Name (2 letter code) [XX]:JP
> State or Province Name (full name) []:Fukuoka
> Locality Name (eg, city) [Default City]:Fukuoka
> Organization Name (eg, company) [Default Company Ltd]:OreOre inc.
> Organizational Unit Name (eg, section) []:
> Common Name (eg, your name or your server's hostname) []:*.sample.com
> Email Address []:
> 
> Please enter the following 'extra' attributes
> to be sent with your certificate request
> A challenge password []:
> An optional company name []:
サーバ証明書作成
openssl ca \
    -config /etc/pki/caCrt/openssl-server.cnf \
    -keyfile cakey.pem -cert cacert.pem \
    -in domain_name.csr \
    -out domain_name.crt.pem \
    -days 825 \
    -extfile /etc/pki/caCrt/san.txt
> Using configuration from /etc/pki/tls/openssl.cnf
> Enter pass phrase for cakey.pem:
> Check that the request matches the signature
> Signature ok
> Certificate Details:
>         Serial Number: 1 (0x1)
>         Validity
>             Not Before: Feb 15 04:46:21 2020 GMT
>             Not After : May 20 04:46:21 2022 GMT
・
・
・
なんかいろいろでる
サーバ証明書の鍵ファイルよりパスフレーズ除去版を作成
openssl rsa \
    -in privkey.pem \
    -out privkey-nopass.pem
> Enter pass phrase for privkey.pem:
> writing RSA key

クライアント証明書

秘密鍵を作成
openssl genrsa \
    -aes256 \
    -out client-privatekey.pem 2048
> Enter pass phrase for client-privatekey.pem:
> Verifying - Enter pass phrase for client-privatekey.pem:
CSR発行
openssl req \
    -new \
    -key client-privatekey.pem \
    -out client.csr
> Enter pass phrase for client-privatekey.pem:
> You are about to be asked to enter information that will be incorporated
> into your certificate request.
> What you are about to enter is what is called a Distinguished Name or a DN.
> There are quite a few fields but you can leave some blank
> For some fields there will be a default value,
> If you enter '.', the field will be left blank.
> -----
> Country Name (2 letter code) [XX]:JP
> State or Province Name (full name) []:Fukuoka
> Locality Name (eg, city) [Default City]:Fukuoka
> Organization Name (eg, company) [Default Company Ltd]:OreOre inc.
> Organizational Unit Name (eg, section) []:
> Common Name (eg, your name or your server's hostname) []:OreOre client
> Email Address []:
> 
> Please enter the following 'extra' attributes
> to be sent with your certificate request
> A challenge password []:
> An optional company name []:
クライアント証明書作成
openssl ca \
    -config /etc/pki/caCrt/openssl-client.cnf \
    -cert cacert.pem \
    -keyfile cakey.pem \
    -out clientcert.crt \
    -infiles client.csr
> Using configuration from /etc/pki/caCrt/openssl-client.cnf
> Enter pass phrase for cakey.pem:
> Check that the request matches the signature
> Signature ok
> Certificate Details:
>         Serial Number: 2 (0x2)
>         Validity
>             Not Before: Feb 15 05:08:00 2020 GMT
>             Not After : Feb 14 05:08:00 2021 GMT
>         Subject:
・
・
なんかいろいろでる
クライアント証明書をpkcs12でエクスポート
openssl pkcs12 \
    -export \
    -in clientcert.crt \
    -inkey client-privatekey.pem \
    -out clientcertinbrowser.pfx -name "hogehoge"
> Enter pass phrase for client-privatekey.pem: [password]
> Enter Export Password: [ブランク]
> Verifying - Enter Export Password: [ブランク]

nginx設定

初期設定のものを書き換え
vi /etc/nginx/conf.d/default.conf
----
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
server {
    listen       443;
    server_name  dev.sample.com;

    ssl on;
    ssl_certificate /vagrant/domain_name.crt.pem;
    ssl_certificate_key /vagrant/privkey-nopass.pem;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}
----


f:id:m_shige1979:20200215210413p:plain

まあ、これでよいかな・・・

■追記
 webブラウザで証明書のインポートが別途必要

Rustのhelloworldを試す。

プログラミング言語

Rust
スクリプト言語のような書き方でC++のような高速化ができるらしいよ
詳しくはわからんがとりあえずやってみる

環境

Mac Book Air(もう古いかも…5年以上前のものだし)

インストール

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");
}
コンパイル
rustc main.rs
./main

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とかいうのを今更少しだけ学習する

なんか

知らんうちにfetchとか出てるんだけどPromiseとかいうやつ返すんですけど
この辺の使い方とか知らないとjqueryajaxしか使えなくなってくるのは恥ずかしい

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フレームワークのアプリ自体が停止する可能性がある・・・

所感

なんかスマートじゃない感じ…
現状、これしか見つからないからこの方法で対応を試みます。

golangでUUIDの生成をライブラリでお試し

仕事でコード書くより

設計の仕事ばっかり、スケジュール管理とかめんどくさいので
他の人やってくんないかな…

UUIDって?

UUID(Universally Unique Identifier)とは、ソフトウェア上でオブジェクトを一意に識別するための識別子である。

*1

ざっくりいうとユニーク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

*1:出典: フリー百科事典『ウィキペディアWikipedia)』