万年素人からHackerへの道

万年素人がHackerになれるまで殴り書きするぜ。

  • ・資産運用おすすめ
    10万円は1000円くらい利益
    資産運用ブログ アセマネ
    • ・寄付お願いします
      YENTEN:YYzNPzdsZWqr5THWAdMrKDj7GT8ietDc2W
      BitZenny:ZfpUbVya8MWQkjjGJMjA7P9pPkqaLnwPWH
      c0ban:8KG95GXdEquNpPW8xJAJf7nn5kbimQ5wj1
      Skycoin:KMqcn7x8REwwzMHPi9fV9fbNwdofYAWKRo

    ginでGroup化したルーティング

    いままでこんな書き方してたが冗長。

    func (controller *ShopsController) Setup() {
            controller.Router.POST("/shops", controller.createShop)
            controller.Router.GET("/shops", controller.listShops)
            controller.Router.GET("/shops/:shop_id", controller.getShop)
            controller.Router.PUT("/shops/:shop_id", controller.updateShop)
            controller.Router.DELETE("/shops/:shop_id", controller.deleteShop)
    }

    Martiniはこうかける GitHub - go-martini/martini: Classy web framework for Go

    Ginにもあった。 GitHub - gin-gonic/gin: Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

    Grouping routes

    func main() {
        router := gin.Default()
    
        // Simple group: v1
        v1 := router.Group("/v1")
        {
            v1.POST("/login", loginEndpoint)
            v1.POST("/submit", submitEndpoint)
            v1.POST("/read", readEndpoint)
        }
    
        // Simple group: v2
        v2 := router.Group("/v2")
        {
            v2.POST("/login", loginEndpoint)
            v2.POST("/submit", submitEndpoint)
            v2.POST("/read", readEndpoint)
        }
    
        router.Run(":8080")
    }

    私の例は、https://github.com/dcu/gin-scaffoldを使ってるので、

    以下のようになる。 controller.Routerを変数v1に置き換えたような感じに。

    func (controller *ShopsController) Setup() {
    
            v1 := controller.Router.Group("/shops")
            {
                    v1.POST("", controller.createShop)
                    v1.GET("", controller.listShops)
                    v1.GET("/:shop_id", controller.getShop)
                    v1.PUT("/:shop_id", controller.updateShop)
                    v1.DELETE("/:shop_id", controller.deleteShop)
            }
    }

    気をつけるのは、v1.GET("", controller.listShops)これ。 /を入れてv1.GET("/", controller.listShops)としてしまうと、 http://localhost:4000/shopsでなくhttp://localhost:4001/shops/のように最後に/が必要だし 色々なページのURLが変わってしまう。

    ginのformでDELETEやPUTのメソッドを送る方法

    ginのフレームワークでできるか?

    HTMLのformmethodPUTとか書いてもおそらくブラウザが対応してない?せいか GET扱いになる。 おそらく、知らないmethodを書くとGETになる仕様なのかも?

    portaltan.hatenablog.com

    これをみるとhiddenに書けばいけるっぽい。 Sinatraが対応してくれてる?

    ここ見る限りモダンなRailsなども対応 html - Why don't the modern browsers support PUT and DELETE form methods? - Stack Overflow

    しかしginは・・・。できなかった・・。

    探すとginのgithubのフォーラム上で

    PUT does not work. Always 404 · Issue #450 · gin-gonic/gin · GitHub

    ん?<form action="/1" method="post"> これは? しかし、これは単にidのことですね。関係ない。

    go get github.com/martini-contrib/method

    インポートする。

    import(
            "ghoulme/controllers"
            "github.com/gin-gonic/gin"
            "net/http"
            "os"
            "github.com/martini-contrib/method"
    )

    これ追加。

    var overrideHandler = method.Override()
    func Override(c *gin.Context) {
            overrideHandler.ServeHTTP(c.Writer, c.Request)
    }
            router := gin.Default()
            router.Use(Override) // これ追加。
            router.LoadHTMLGlob("templates/**/*")
            controllers.Setup(router

    これで一応putできるようになった。

    が・・・・つねに404となる。 誰か教えて。 またはわかったらまた記事書きます。

    golang template テンプレートの優先順

    テンプレートの優先順。

    ginのテンプレートの機能で以下のようにテンプレートを読む設定する。

    router := gin.Default()
    router.LoadHTMLGlob("templates/*/*.tmpl")

    こうすればtemplates/なんとか の[なんとか]が自由になる。

    templates/shop/index.tmpl templates/aho/index.tmpl

    の2つ同じファイル名、ただし親フォルダが違う。

    呼ぶ側はこんな感じ。c*gin.Contextだ。

            c.HTML(http.StatusOK, "index.tmpl", gin.H{
                    "title": "shop",
                    "body": shopsResponse,
            })

    これでやると、templates/shop/index.tmplの方が呼ばれた。 おそらくアルファベット順でshopとahoだとaよりもsの方が後だが、 s開始のshopが呼ばれたのは、後からロードされたのが上書きしたから?

    試しに、sよりもtの方が後なのでtemplates/tra/index.tmplとテキトーに作った。 そうすると、templates/shop/index.tmplではなく、templates/tra/index.tmplが優先されてた。

    しかし、明示的に同じファイルがある時の指定方法はどうやるのかしら?