Golangå¨è¾ºã®ãã¼ã«ããããã使ããªããGin Web Frameworkã§APIãä½ã
Golangã§éçºããä¸ã§ã©ã¤ãã©ãªã®ä¾åé¢ä¿è§£æ±ºã©ãããã¨ããObject Relational Mapping(ORM)ã©ãããã¨ããhot deployããªããéçºããã®ã©ãããã¨ãããã¨æããã§ãããã®è¾ºããè»½ãæ¸ããªããAPIä½ã£ã¦ããããã¨æãã¾ãã
Docker使ã£ã¦éçºãããããã®è§£èª¬ã¯ä»¥åã®ããã°ãåç §ããããã
ã§ãããã¨
- Golangã§ä¾åã©ã¤ãã©ãªã®ç®¡ç(ã¨ç¾å ´è¨ã£ã¦ãããã®ãã¯å¾®å¦)
- ORMã使ã£ãDBã¢ã¯ã»ã¹
- Macä¸ã§ã½ã¼ã¹ã³ã¼ãã夿´ããéãDockerã³ã³ããã«ä¿®æ£ãåæ ããã¦ãã¬ã¼ã ã¯ã¼ã¯ããªãã¼ãããã
- Webãã¬ã¼ã ã¯ã¼ã¯ãå©ç¨ããAPIéçº
ãã¼ã«ã¨ç°å¢
- Mac OSX 10.9.5 Mavericks
- Vagrant 1.7.2
- Fresh (c4a501e4002c78dfd6bd519001a580e59a9db4b6)
hot deployã®ããã®ãã¼ã«ã
pilu/fresh · GitHub - Godep (58d90f262c13357d3203e67a33c6f7a9382f9223)
ä¾åé¢ä¿ç®¡çãã¼ã«() - APIã§ä½¿ç¨ãã¦ããå種ã©ã¤ãã©ãªã®ãã¼ã¸ã§ã³
以ä¸åç §
golang-gin-api/Godeps.json at master · takasing/golang-gin-api · GitHub
Frameworkã®é¸å®
æ¨ä»ã§ã¯Golangã®Webãã¬ã¼ã ã¯ã¼ã¯ããã¤ãããã¾ããã
- Revel
- Martini
- Beego
- Goji
ãã«ã¹ã¿ãã¯ãã¬ã¼ã ã¯ã¼ã¯ã¯å¦ç¿ã³ã¹ãé«ãã®ã§ããã¾ããã
Martiniã¯ããã©ã¼ãã³ã¹ããã¾ããããªãã¿ãããªã®ã§ãMartiniã©ã¤ã¯ã§ããã©ã¼ãã³ã¹æ¹åãããgojiãginã鏿è¢ã«ãªãã¾ããã
gojiã®å£²ãã¯graceful restartã ã£ããããã®ã§ãããDockerç°å¢ã ã¨Blue-Green deploymentããã¨æãã®ã§ãã¾ãéè¦ã§ã¯ãªãã¨æãã¾ãã
ãã¤ãgojiããginã®ã»ããEndpointã«å·®ãè¾¼ã颿°ã¤ã³ã¿ã¼ãã§ã¼ã¹ãç°¡æ½ãªã®ã§ãä»åã¯Ginã使ç¨ãããã¨ã«ãã¾ãã
ä¾åã©ã¤ãã©ãªã®ç®¡çã«ã¤ãã¦
ãããã¾ã Golangãæªéæã¨ãããã¾ã ã¾ã ã ãªã¨ããã¨ãããªãã§ãããGoã®ææ³ã¨ãã¦
æåããããGoã®ç®æ¨ã¯ãMakefileãMakefileã«å¤ããæ§ã ãªç¾ä»£çãªæ§æãã¡ã¤ã«ãæ¸ãå¿ è¦ããªããã ã½ã¼ã¹ã³ã¼ãèªä½ã«ããæ å ±ã®ã¿ã使ã£ã¦Goã®ã³ã¼ãããã«ãã§ããããã«ãããã¨ã§ããã
ã¨ã
æ°ããGoã³ãã³ãã®ç®æ¨ã¯ãGoããã°ã©ã ã¯å¿ è¦ãªã¤ã³ãã¼ãæãæ¸ãã¨ãããã¨ä»¥ä¸ã«éçºè å´ã§æ§æãã¡ã¤ã«ã追å ã®ä½æ¥ãããã«ã³ã³ãã¤ã«ã§ããããã«ããå¿ è¦ããããã¨ãããç§ãã¡ã®çæ³ã¸å帰ãã¦ãã¾ãã
Goコマンドについて - The Go Programming Language
ã¨ããèããããã¾ãã
ã¤ã¾ãè¨å®ãã¡ã¤ã«(ï¾â¿ï¾)ï½²ï¾ï¾ã£ã¦ãã¨ã§ããã
ãããã©ããããã¨ãã¨ããã¨ãgo get
ããã ãã§ã©ã¤ãã©ãªè½ã¨ãã¦ãããã®ã§ããã䏿¹ã§.goãã¡ã¤ã«ã«ã¯
import "github.com/gin-gonic/gin"
ã¨ããæ¸ãããªãã®ã§ãã©ã¤ãã©ãªã®ãã¼ã¸ã§ã³æå®ãã§ããªãããã§ããããã
å¤é¨ã©ã¤ãã©ãªä½¿ã£ããã¨ãã人ã¯ãããã¨æããã§ããã©ãã©ã¤ãã©ãªã¯æ®éã«ãã°ä»è¾¼ã¾ãã¦ããã®ã§ããã¼ã¸ã§ã³æå®ããªãã¨ãæ¯ågo get
ãã¦éçºã¡ã³ãã¼éã§ç°ãªããã¼ã¸ã§ã³ã§éçºãããã¨ããå±ããã¹ã¿ã¤ã«ãä½åãªããããã ãã§ãªãã使ããã¢ããªã±ã¼ã·ã§ã³èªä½ãã©ã¤ãã©ãªã®ãã°ã«ãã£ã¦åä½ããªããªãã¨ããå¯è½æ§ãããã¾ã(ãã¹ããã¡ããã¨æ¸ãã¾ãããããã£ã¯ãï½½ï¾ï¾ï½¾ï¾ï¾ï¾ï½¼ï¾)ã
ä¸å¿Golangãå
¬å¼ã§æ¨å¥¨ãã¦ããã¹ã¿ã¤ã«ããããã®ã®ãããã¾ã§ç¢ºç«ãã¦ããªãã®ãç¾ç¶ã§ãã
PackageManagementTools · golang/go Wiki · GitHub
çæããç®ã§è¦å®ãã¾ãããã
ä»åã¯ããããªã©ã¤ãã©ãªã¨ããã¼ã«ã§ä½¿ããã¦ããGodepã使ç¨ãã¾ãã
Godepã®ã¹ã¿ã¤ã«ã¨ãã¦ã¯ãã©ã¤ãã©ãªã®ã½ã¼ã¹ã³ã¼ããèªåã®ã¢ããªã±ã¼ã·ã§ã³ã®ãªãã¸ããªã«ã³ããããã¦ä½¿ç¨ããã¨ãããªããªãã¯ã¤ã«ããªæãã«ãªã£ã¦ãã¦ãã¾ãæ°ã«å
¥ããªãã£ããããã®ã§ããã誰ãã¤ã±ã¦ããã¤ä½ã£ã¦ãã ããã¾ããããï½
åé ã§ãä¾åã©ã¤ãã©ãªã®ç®¡ç(ã¨ç¾å ´è¨ã£ã¦ãããã®ãã¯å¾®å¦) ãã¨æ¸ããã®ã¯ãããããã¨ã§ãã
ã¢ããªã±ã¼ã·ã§ã³ã®è§£èª¬
ã¨ã³ããã¤ã³ãã®ä½æ
Ginã§ã¯Sinatraãªã©ã¨åæ§ã«ãä¸ã¤ã®ã¨ã³ããã¤ã³ãã«é¢æ°ã渡ãã¦å¦çãè¡ãã¾ãã
ãã®éã®ã¡ã½ããã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯github.com/gin-gonic/gin/gin.go
ã§ã·ã³ãã«ã«å®ç¾©ããã¦ãã¾ãã
type ( HandlerFunc func(*Context) ...
ãªã®ã§ãã¨ã³ããã¤ã³ãã«å¯¾ãã颿°ãå®ç¾©ãã¦ããã®é¢æ°ã«å¯¾ããåç
§ãã«ã¼ã¿ã¼ã«æ¸¡ãã¾ãã
routes/article.go
func GetArticle(c *gin.Context) { id := c.Params.ByName("id") v, err := c.Get("dbMap") if err != nil { log.Printf("error: %s", err.Error()) c.JSON(http.StatusBadRequest, gin.H{"status": "bad request"}) return } dbMap, ok := v.(*gorp.DbMap) if !ok { c.JSON(http.StatusBadRequest, gin.H{"status": "bad request"}) return } art, err := dbMap.Get(model.Article{}, id) if err != nil { log.Printf("error: %s", err.Error()) c.JSON(http.StatusInternalServerError, gin.H{"status": "db error"}) return } if art == nil { c.JSON(http.StatusNotFound, gin.H{"status": "not found"}) return } c.JSON(http.StatusOK, gin.H{"status": "ok", "article": art}) }
routes/router.go
func Init(app *app.App) *gin.Engine { router := gin.Default() router.Use(app.AppendEnv) v1 := router.Group("/v1") { v1.Use(filter.Auth) v1.GET("/article/:id", GetArticle) v1.POST("/article", PostArticle) } return router }
ããã§/v1/article/1
ãªã©ã¨ãªã¯ã¨ã¹ããæ¥ãå ´åã¯GetArticleã¡ã½ãããå®è¡ãããããã§ãã
filterå¦ç
ä¸è¨ã®ããã«ã¨ã³ããã¤ã³ããè¨å®ããããåã®é¨åã§Useã¡ã½ããã使ã£ã¦ã¡ã½ãããæ¸¡ãã¦ãããã¨ã§ãfilterã®ãããªå¦çããããã¨ãã§ãã¾ãã
ããã§ã¯DbMap(å¾è¿°)ãContextã«è¿½å ããå¦çã¨ãCookieã«ããã¦ã¼ã¶ã¼èªè¨¼ãè¡ã£ã¦ãã¾ãã
ãã®å ´åãGinã§ã¯åã颿°ã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ãªã®ã§ã¨ã¦ãã·ã³ãã«ã§ãããã¨ããããã¾ãã
DBã¢ã¯ã»ã¹ã¨ORM
ä»åã¯PostgreSQLã®DBã«ã¢ã¯ã»ã¹ããããã«ãã¦ãã¾ãã
db/postgres.go
package db import ( _ "github.com/lib/pq" // for sql.Open "github.com/go-gorp/gorp" "database/sql" "golang-gin-api/model" ) func InitDb() *gorp.DbMap { db, err := sql.Open("postgres", "host=db user=takasing dbname=toyo password=takapass sslmode=disable") if err != nil { // handle error } dbmap := &gorp.DbMap{Db: db, Dialect: gorp.PostgresDialect{}} dbmap.AddTableWithName(model.Article{}, "articles").SetKeys(true, "Id") dbmap.AddTableWithName(model.User{}, "users").SetKeys(true, "Id") return dbmap }
database/sql
ããã±ã¼ã¸ã使ç¨ãã¦Dbã¸ã®æ¥ç¶æ
å ±ãçæãã¦ãã¾ãã
ããã§æ³¨æãããã®ãimportæã®ã¨ããã
_ "github.com/lib/pq"
Golangã§ã¯ä½¿ç¨ãã¦ããªãimportæãã½ã¼ã¹ã³ã¼ãã«æ®ã£ã¦ãããã³ã³ãã¤ã«ãéããªãã®ã§ãããä»åã®DBã®ãã©ã¤ãããã«ã½ã¼ã¹ã³ã¼ãä¸ã§ä½¿ç¨ããã¦ããªããã©å¿
è¦ãªãã®ã«é¢ãã¦ã¯ã¢ã³ãã¼ã¹ã³ã¢ãã¤ãã¦importæãæ¸ããã¨ã§ã³ã³ãã¤ã«ã¨ã©ã¼ãåé¿ãããç¡äºDBã¸ã®æ¥ç¶ãçæããã¾ãã
(ããã«æ°ã¥ããçµæ§ããã£ã(^q^))
ã¾ããGolangã§ã¯ããã±ã¼ã¸å
ã®åã®ãã£ã¼ã«ããã¡ã½ãããå¤é¨ã«éãæã¯ãå
é ã®æåã大æåã«ãããã¨ã§ãããå®ç¾ãã¦ãããã§ããããã®å ´åDBã®ã«ã©ã åã¨ç°ãªããã¨ãããã¾ãã
ãã®ã¾ã¾ã§ã¯ãã¾ããããã³ã°ãã¦ãããªãã®ã§ãGolangã®ã¿ã°ã®æ©è½ã使ã£ã¦é¢é£ä»ãã¦ããã¾ãã
model/article.go
type Article struct { Id int `json:"id"` Title string `json:"title" validate:"min=4,max=64,nonzero"` Content string `json:"content"` CreatedAt time.Time `json:"created_at" db:"created_at"` }
ã¿ã°ã¯ããªãã¼ã·ã§ã³ã¨ãjsonã®ãããã³ã°ã¨ãã«ã使ããã¾ãã
å®è¡
$ vagrant up $ vagrant ssh core@core-01 ~ $ ./share/container.sh -pgx core@core-01 ~ $ docker exec -it postgres bash root@6b18b5a5b43c:/# cd /project root@6b18b5a5b43c:/# sh database.sh root@6b18b5a5b43c:/# exit core@core-01 ~ $ docker logs -f golang ... app log here ...
ãã©ã¦ã¶ã«172.17.8.102
ã®ãã¡ã¤ã³ã«uid
ã§valueã1ã«ãã¦Cookieç¼ãã¾ãã
ããã¦Advanced REST API Clientã¨ãã§APIãå©ãã¦ã¿ã¦ãã ããã
詳ããã¯ã½ã¼ã¹ã³ã¼ãã御覧ãã ããï½
ææ
- åã¯ä¼ç¤¾å
¥ã£ã¦ããããã°ã©ã æ¸ãå§ããã¯ããªã®ã§ãJavaã¨Rubyããã¾ã¨ãã«æ¸ãã¦ãªããã¨ãããã°ã©ããªãã§ãããGolangã¯ã¾ã ã¾ã ãããã°ã¨ããããã£ããã
ãã¤ã³ã¿(^q^) - Ginã¯ã¾ã æ°ãããã¬ã¼ã ã¯ã¼ã¯ãªã®ã§ãããã¥ã¡ã³ãããã¾ããªãã®ã§ãããMartiniãã²ãã¦ã¯Sinatraã¤ã³ã¹ãã¤ã¢ã¨ããã¨ããã«çç®ãã¦ããã¥ã¡ã³ãæ¢ãã°ããç¨åº¦åèã«ãªãã®ã§ã¯ãªãã§ããããã
ãã¬ã¼ã ã¯ã¼ã¯èªä½ã¯ã·ã³ãã«ãªã®ã§ãGolangã®è¨èªä»æ§ããããç¨åº¦é ã«å ¥ãã°ç°¡åã«APIã¯æ¸ãããã§ããã - Golangçã«ãããã®ãªããã¨ãªãã§ããã©ãè¤æ°ã®è¿ãå¤ãã¤ãã£ã¦errorãå¶å¾¡ããã®ã§ããã¾ããã¨æ¸ããªãã¨ã³ã¼ãã¯é·ããªãã¾ããããããããã
TODO
- Dockerã¾ããã®è¨å®ã¯Docker Composeã¨ãDocker Machineã¨ãããã®ã§æ¸ãæãããã