最近のはやりに乗って、GoとBlockchainの両方をこの動画(シリコンバレーエンジニアの酒井潤さんの「現役シリコンバレーエンジニアが教えるGoで始めるスクラッチからのブロックチェーン開発入門」https://www.udemy.com/course/go-blockchain/
)を見て勉強し始め、ここ最近終了したところなのだが、なんせbackendもblockchainもまるで初心者なもので、この動画を通してGOの理解しにくかった部分を自分なりにかみくだいてアウトプットしていこうと思う。僕のようにバックエンド完全初心者の手助けになれば幸いです
MarshalJsonって何?
MarshalJsonというのは、構造体→JSON形式に変換することらしい。
(逆にUnMarshalJsonというのは、JSON形式→構造体に変換すること)
しかし、この講座をみていると、少し不思議な書き方をしていた。
type Block struct {
timestamp int64
nonce int
previousHash [32]byte
transactions []*Transaction
}
func (b *Block) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
//型 //json上における名前
Timestamp int64 `json:"timestamp"`
Nonce int `json:"nonce"`
PreviousHash string `json:"previous_hash"`
Transactions []*Transaction `json:"transactions"`
}{
//入れたい値
Timestamp: b.timestamp,
Nonce: b.nonce,
PreviousHash: fmt.Sprintf("%x", b.previousHash),
Transactions: b.transactions,
})
}
"encoding/json"というパッケージの中にMarshalという関数があるのに、わざわざMarshalJsonという関数をつくっている。(しかも少し複雑な書き方で)
これが何なのか調べたところ、プログラムと実際のJson内で異なる型を使いたいときがあるとき、このようにひと手間加えてMarshalJsonするらしい。
sync.Mutexという謎の型
こんな記述があった
func (bc *Blockchain) SyncNeighbors() {
bc.muxNeighbors.Lock()
defer bc.muxNeighbors.Unlock()
bc.SetNeighbors()
}
なんやら排他制御を行いたいときに、使うらしい。
理解してしまえば簡単だが、並列処理などで処理の衝突(当時に同じ配列を書き換える、など)を防ぐために、
Lockでその変数に鍵をかけ一つだけしか処理をできないようにし、
deferで関数の最後にUnlockをして、鍵を開けているということらしい
httpリクエストを飛ばす方法
少しできる人からしたら簡単なことだろうが、まったく知らなかったのでメモ。
// request structの作成
req, _ := http.NewRequest(
"Post",
"https://test",
bytes.NewBuffer([]byte("request body"),
)
// そのheaderを指定
req.Header.Add("Content-Type", "application/json")
// クライアントを初期化
var client *http.Client = &http.Client{}
//今回の動画見る感じ、これでも行ける?
client := &http.Client{}
// そこからリクエストを飛ばす
resp, _ := client.Do(req)
// そのリスポンスをprint
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
エンドポイントをいじりたいときは、
方法1(結合)
base, _ := url.Parse("https://test/mypage/")
reference, _ := url.Parse("myPicture?a=1&b=2")
endpoint := base.ResolveReference(reference).String() // URLを結合する
方法2(変数名を入れる)
endpoint := fmt.Sprintf("http://%s/transactions", n)
こんな感じで少しいじってやる。
flag
コマンドライン引数を指定できる。
今回だとこんな感じで、port番号とgatewayを指定していた。
func main() {
port := flag.Uint("port", 8080, "TCP Port Number for Wallet Server")
gateway := flag.String("gateway", "http://127.0.0.1:5000", "Blockchain Gateway")
flag.Parse()
app := NewWalletServer(uint16(*port), *gateway)
app.Run()
}
また、気になったことがあれば随時更新していきます。
講義を受けている途中はちんぷんかんぷんだったが、この記事を書くにつれ頭の中でまとまって、Goを割と理解できるようになってきたきがする。サーバサイドあたりの知識が弱いのでこれからもGo書きながらいろいろと勉強していきたい。今度はgoでDappsとか作ってみたいな。