🧟

goで連想配列フォームつくるよー

2022/02/08に公開

phpって便利ですね。いやgoでwebつくるのがまちがってるのかな?
表題の件ですが、一筋縄ではなかったです。

phpみたく「name="item[][name]"」みたいにできないのです。
まぁ単純なスライス配列であれば「name="item[]"」をそのまま

router.POST("/inc/contact", func(c *gin.Context) {
	c.Request.ParseForm()
	item := c.Request.Form["item[]"]
})

みたいに受け取ってそのままfirestoreとかにいれたり、
ループさせてDBに入れたりすればいいと思うんす。

でもこれが連想になると、mapになると途端にしんどくなります。

まず "github.com/gorilla/schema" これいれます。
これをいれると

https://pkg.go.dev/github.com/gorilla/schema

<form>
	<input type="email" name="Emails.0">
	<input type="email" name="Emails.1">
	<input type="email" name="Emails.2">
</form>

<form>
	<input type="text" name="Name">
	<input type="text" name="Phones.0.Label">
	<input type="text" name="Phones.0.Number">
	<input type="text" name="Phones.1.Label">
	<input type="text" name="Phones.1.Number">
	<input type="text" name="Phones.2.Label">
	<input type="text" name="Phones.2.Number">
</form>

こういうんを取得した後デコードで型にはめてくれます。
この例は優しいです。自分の場合は、

<input type="text" name="item.0.Ary.1.Val" value="...">

自分の場合というか、普通こういうのは固定べた書きなんてなくてどれだけ放り込まれるか分からなかったりするもんですよね。このように

{{range $i, $v := .item.Loooop}}
<li>
	<input type="text" name="item.{{$i}}.Val" value="{{$v.Val}}" class="form-control">
</li>
{{end}}

連想なんでこれがもう一個深くなるケースもあった訳です。でもこれでできると言えばできます。まず struct るんですが、連想なので、

type Form struct {
	name string
	mail string
	itemMap []Map // 連想mapのケース
	itemSlice []Ary // 配列スライスのケース
}
type Map struct {
	Ary []Ary
}
type Ary struct {
	Val string
}

みたいに書きます。ここで「[]string」でいいのでは?って思う方は慣れた方です。
でも「gorilla/schema」はそれだと認識できません。
「gorilla/schema」を自作するか上記のように入れ子を定義するかしないといけません。

取得やデコードはカンタンです。

//パラメータスキーマ処理
decoder := schema.NewDecoder()
var aaa Form
err = decoder.Decode(&aaa, c.Request.Form)

上の構造体Formの型にフォームのパラメータを合致させてくれます。ここで終わりですが、いらん空白の要素を消したいとか、データ構造がこれにより変更になってしまうなど、色々玉突き的に対応が必要になるので割と地獄です。

そういう記事です。

Discussion