Golangでx-www-form-urlencodedのリクエストを投げる
やりたいことはタイトルそのままです。
parameter=hoge
をhttpでPOSTする方法は以下です。
form := url.Values{} form.Add("paramter", "hoge") body := strings.NewReader(form.Encode()) req, err := http.NewRequest("POST", "https://example.com", body) if err != nil { log.Fatal(err) } req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
References
Golangのnew()とmake()の違い
この記事は Go (その3) Advent Calendar 2017 の5日目の記事です。
本記事では、変数の宣言に用いられる組み込み関数new()
とmake()
の違いについてまとめます。
まとめ
さっそくですが、違いを表にまとめます。
new(T) | make(T) | |
---|---|---|
対象 | 任意の型 | slice, map, channelのみ |
初期化 | 初期化しない(ゼロ値になる) | 初期化する |
返り値 | *T | T |
対象と初期化について
new()
とmake()
で、初期化しない/するの違いは、
slice, map, channelが、内部にデータ構造を持つことからきています。
以下にruntime
パッケージで、それぞれ型が定義されている箇所を引用します。
一番理解しやすいのが、sliceです。array(実データ), len, capを初期化してあげる必要があるため、make()
が用意されています。
slice
type slice struct { array unsafe.Pointer len int cap int }
https://golang.org/src/runtime/slice.go#L11-15
map
type hmap struct { // Note: the format of the Hmap is encoded in ../../cmd/internal/gc/reflect.go and // ../reflect/type.go. Don't change this structure without also changing that code! count int // # live cells == size of map. Must be first (used by len() builtin) flags uint8 B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items) noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details hash0 uint32 // hash seed buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0. oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated) extra *mapextra // optional fields }
https://golang.org/src/runtime/hashmap.go#L106-120
channel
type hchan struct { qcount uint // total data in the queue dataqsiz uint // size of the circular queue buf unsafe.Pointer // points to an array of dataqsiz elements elemsize uint16 closed uint32 elemtype *_type // element type sendx uint // send index recvx uint // receive index recvq waitq // list of recv waiters sendq waitq // list of send waiters // lock protects all fields in hchan, as well as several // fields in sudogs blocked on this channel. // // Do not change another G's status while holding this lock // (in particular, do not ready a G), as this can deadlock // with stack shrinking. lock mutex }
https://golang.org/src/runtime/chan.go#L31-50
初期化について補足
Effective Goでは、new()
では初期化が行われない、つまりゼロ値となることについて、helpfulであると述べられています。
これはゼロ値自体が意味を持つ場合には、初期化しているのと同じだけの意味があるということです。
Effective Goで述べられている例ですが、sync.Mutex
では以下のようにゼロ値自身がunlockなstateを表現します。
// A Mutex is a mutual exclusion lock. // The zero value for a Mutex is an unlocked mutex. // // A Mutex must not be copied after first use. type Mutex struct { state int32 sema uint32 }
自身で型を定義する際には、NewMyType()
のようなコンストラクタを用意する場合が多いでしょう。このときにゼロ値自身に意味を持たせ、new()
と組み合わせることでよい設計となると思います。
最後に
自分自身もあまりnew()
とmake()
の違いを認識できていなかったので、調べてまとめることができてよかったです。あといつか読もう読もうと思って着手できていなかったruntime
パッケージを読むきっかけにもなったので、思いの外収穫が多かったです。Goはソースコードにドキュメントレベルでコメントが書いてあるので、読むだけでなるほどと思うことが多く、とても勉強になります。
Githubの履歴を確認したらちょうどGoを書き始めてから1年が経過しました。書けば書くほど好きになっていくので、まだまだ書きますよー!
あぁ。水色gopherくんぬいぐるみ欲しいなぁ。。。
References
go tool compileの使い方
少し試したものの、忘れそうなのでメモ書きとして残します。
サンプルコード
package main import "fmt" func main() { fmt.Println("hello world") }
オブジェクトファイルの生成
-S
が1つだと標準出力のみです。2つだと.o
ファイルが生成されます。
$ go tool compile -S -S main.go "".main STEXT size=120 args=0x0 locals=0x48 0x0000 00000 (main.go:5) TEXT "".main(SB), $72-0 (中略) 0x0000 65 48 8b 0c 25 00 00 00 00 48 3b 61 10 76 62 48 eH..%....H;a.vbH 0x0010 83 ec 48 48 89 6c 24 40 48 8d 6c 24 40 48 c7 44 ..HH.l$@H.l$@H.D 0x0020 24 30 00 00 00 00 48 c7 44 24 38 00 00 00 00 48 $0....H.D$8....H 0x0030 8d 05 00 00 00 00 48 89 44 24 30 48 8d 05 00 00 ......H.D$0H.... 0x0040 00 00 48 89 44 24 38 48 8d 44 24 30 48 89 04 24 ..H.D$8H.D$0H..$ 0x0050 48 c7 44 24 08 01 00 00 00 48 c7 44 24 10 01 00 H.D$.....H.D$... 0x0060 00 00 e8 00 00 00 00 48 8b 6c 24 40 48 83 c4 48 .......H.l$@H..H 0x0070 c3 e8 00 00 00 00 eb 88 ........ rel 5+4 t=16 TLS+0 rel 50+4 t=15 type.string+0 rel 62+4 t=15 "".statictmp_0+0 rel 99+4 t=8 fmt.Println+0 rel 114+4 t=8 runtime.morestack_noctxt+0 (中略) type..importpath.fmt. SRODATA dupok size=6 0x0000 00 00 03 66 6d 74 ...fmt gclocals·69c1753bd5f81501d95132d08af04464 SRODATA dupok size=8 0x0000 02 00 00 00 00 00 00 00 ........ gclocals·e226d4ae4a7cad8835311c6a4683c14f SRODATA dupok size=10 0x0000 02 00 00 00 02 00 00 00 00 03 .......... gclocals·33cdeccccebe80329f1fdbee7f5874cb SRODATA dupok size=8 0x0000 01 00 00 00 00 00 00 00 ........
オブジェクトファイルから実行コードを生成
$ go tool link main.o $ ls a.out main.go main.o $ ./a.out hello world
オブジェクトファイルに定義されているシンボルの表示
$ go tool nm main.o U 44c T %22%22.init 517 B %22%22.initdone· 3b5 T %22%22.main 507 R %22%22.statictmp_0 U fmt.Println U fmt.init 6de R gclocals·33cdeccccebe80329f1fdbee7f5874cb 6cc R gclocals·69c1753bd5f81501d95132d08af04464 6d4 R gclocals·e226d4ae4a7cad8835311c6a4683c14f 4ea ? go.info.%22%22.init 4cd ? go.info.%22%22.main 507 ? go.range.%22%22.init 4ea ? go.range.%22%22.main 4c2 R go.string."hello world" U runtime.algarray 517 R runtime.gcbits.01 560 R runtime.gcbits.03 U runtime.morestack_noctxt U runtime.throwinit 646 R type.*[1]interface {} 5c3 R type.*[]interface {} 528 R type.*interface {} 6c6 R type..importpath.fmt. 633 R type..namedata.*[1]interface {}- 5b1 R type..namedata.*[]interface {}- 518 R type..namedata.*interface {}- 67e R type.[1]interface {} 5fb R type.[]interface {} 561 R type.interface {} U type.string
実行コードの逆アセンブリ
$ go tool objdump a.out (略)
References
Golangで主成分分析する
前回の記事では、 多次元正規分布から乱数を生成する方法を書きました。 今回は、このデータを使って主成分分析(PCA)を行っていきます。
PCAの詳細については、書籍や他の記事などで十分存在していると思うので、そちらを探してみてください。 分散を最大化する方向に軸を取るのか、射影誤差の最小化を行うのかなど複数の解釈が同じ数式に帰着するのも面白いですね。結局は、共分散行列の固有値問題に帰着するのですが。
まず、今回の対象データですが、 の共分散行列を用いて生成した擬似乱数(2次元×10000個)を使用します。 散布図を書くと以下のようになります。
Golangのstatパッケージでは、PCAを行ってくれるPrincipalComponents
メソッドがあるので、こちらを利用します。
コード
まず擬似乱数の生成です。のちほど使うPrincipalComponents
の引数がmat.Matrix
なので、
mat.NewDense
で生成した*mat.Dense
型のy
に乱数を格納していきます。
ちなみに*mat.Dense
型はmat.Matrix
型のinterfaceを満たします。
y := mat.NewDense(N, d, nil) for i := 0; i < N; i++ { rnd, _ := MultiNorm(mat.NewVecDense(d, []float64{0.0, 0.0}), mat.NewSymDense(d, []float64{3.0, 0.5, 0.5, 1.0}), ) y.SetRow(i, mat.Col(nil, 0, rnd)) }
次にPCAの実行です。stat.PC
型がPCA用の型となります。
var pc stat.PC ok := pc.PrincipalComponents(y, nil)
PCAのあとはデータを射影していきます。次元削減を目的とする場合はk
で残したい次元数を指定できます。
k := 2 var proj mat.Dense proj.Mul(y, pc.VectorsTo(nil).Slice(0, d, 0, k))
以上をまとめたコード全体は次のようになります。
giste8f284fa0ed27fa4802ebe0867a795aa
PCA後の散布図は以下のようになりました。
References
Golangで多次元正規分布を生成する
前回の記事も書きましたが、 Golangのrandパッケージでは、 一次元正規分布の乱数生成が可能です。 今回は、多次元正規分布から乱数を生成する方法についてまとめます。
どうやって生成するか
まずPRMLから引用します。
平均,共分散を持つ多変量ガウス分布に従うベクトル値の変数を生成するには, の形を取るコレスキー分解(Cholesky decomposition)を用いればよい(Press et al., 1992). このとき, もしがベクトル値の確率変数であり, その各要素が独立で, 平均0, 分散1のガウス分布に従うとすれば, は平均 , 共分散のガウス分布に従う.
rand.NormFloat64()
は、まさに平均0、分散1の一次元正規分布の乱数を生成してくれるので、
与えられたをコレスキー分解すれば多次元正規分布からの乱数生成ができます。
gonumのmatパッケージでは、Cholesky
型のFactorize
メソッドでコレスキー分解ができるので、こちらを使って多次元正規分布からの乱数を生成します。
コード
実装は以下です。MultiNorm
関数として実装しています。
散布図を描くコードも含んでいるので、少し長いです。。。
gist3609a47a7f572bd8e479ef120dae3f0e
実行結果
References
- Package rand - The Go Programming Language
- Package mat - Godoc
- Bishop, C. M. "パターン認識と機械学習." パターン認識と機械学習 (2008).
- 多次元正規分布の発生 - frontier45
- Golangで正規乱数 - 逆さまにした
Golangで正規乱数を生成する
インフラ/ネットワークエンジニアのためのネットワーク・デザインパターン 実務で使えるネットワーク構成の最適解27を読んだ
前作であるインフラ/ネットワークエンジニアのためのネットワーク技術&設計入門を読んでから、少し間が空いてしまいましたが、続編となるインフラ/ネットワークエンジニアのためのネットワーク・デザインパターン 実務で使えるネットワーク構成の最適解27 - みやた ひろしを読みました。
感想
まず、読んでいて一番の感想は、本自体の構成も設計されている ということです。 ネットワークを設計するにあたって、ネットワークを以下の4つに分類し、それぞれについて述べる形で整理された構成となっています。
さらに各ゾーンを大中小の3規模にわけ、それぞれ2つずつデザインパターンを述べる構成となってています。 各ゾーンの説明が小さい順に記載されており、設計の考え方自体は一貫しているので、大規模ネットワークになっても理解しやすかったです。
さらに各節の中でも項目が一貫しており、以下のようになっています。
- 物理構成、論理構成
- 機器構成設計、物理構成設計、VLAN設計、IPアドレス設計、ルーティング設計
- 障害設計
- 運用設計
これに加えて各構成で独自に必要な設計(負荷分散設計やSTP設計など)は個別に述べられています。
各構成で考え方が一貫している一方で、同じ話が何度か登場します。 内容が重複してしまうのは一長一短ですが、個人的には、何回も同じトピックが出るので理解が染み込んでくる点、あとで読み返す際にその節だけ読めばいい点で、丁度よいと感じました。
個人的にヒットしたところ
LAGを使ってSTP構成を組む場合に、物理ポート障害が発生するとSTPの再計算となる話が載っています。
STPの仕組みとしてコストがあり、このコストに応じてL2ループが発生しないようになっていることはわかっていたのですが、障害時に余計な再計算をさせないように値を設定する、といった意識できていなかった話が載っており、学びが多かったです。
こういう人におすすめ
ネットワーク設計に多少の経験があるので、デザインパターンを体系的に整理したいという方におすすめです。
一方で、OSPFやBGP、IPsecなど各種の設定で注意すべき設定などは書かれているものの基本的な仕組みなどの記載は少ないので、ネットワーク技術の知識に不安がある場合は、本書の前に前作のインフラ/ネットワークエンジニアのためのネットワーク技術&設計入門を読むのがいいと思います。
どちらも構成がわかりやすいのと簡潔にまとめられているので数日あれば十分読めると思います。 本書に関しては、ページを捲る手が止まらず実質2日くらいで読み切ってしまいました。
インフラ/ネットワークエンジニアのためのネットワーク・デザインパターン 実務で使えるネットワーク構成の最適解27 - みやた ひろし
いつもはkindle派な自分ですが、データフローを正常時と障害時で見比べたりしながら読むと理解が深まるので紙の書籍がおすすめです。