生涯未熟

生涯未熟

プログラミングをちょこちょこと。

Golang初心者がGinでTODOアプリ作ってみたよ

Goに愛を注ぐことが最近の楽しみな私です。

今回はGoのWAFであるGinを使ってTODOアプリを作ってみました。 あんまりGinの情報が無いので何かの参考になればなと。

「能書きはいいからコード見せろや!」って方はこちらのリポジトリを見て下さいまし。 github.com


Ginのお勉強

まずはGinってなんぞや?ってところから学びました。

かるーくGinのリポジトリにあるREADMEに目を通して、 そっから「プロジェクトをどういう形にすればいいんだ?」ってなったので、エウレカさんのテックブログの記事を参考にしました。

developers.eure.jp

あとはGinやxormのドキュメントをチラチラと。

gin - GoDoc

Documentation - xorm: Simple & Powerful ORM Framework for Go Programming Language

構成

構成はほぼエウレカさんの記事のままですね。

.
├── README.md
├── controllers
│   └── task.go
├── main.go
├── models
│   └── task.go
└── views
    └── home.tmpl

説明

main.go

main.goでは

  • 各routeの設定
  • Controllerを使って取得した値をViewに渡す

ってなことをやってます。

package main

import (
  "gin-sandbox/controllers"
  "github.com/gin-gonic/gin"
  "net/http"
)

func main() {
  router := gin.Default()

  // viewディレクトリを指定
  router.LoadHTMLGlob("views/*")

  router.GET("/", func(c *gin.Context) {
    ctrl := task.NewTask()
    
    // ControllerのGetAllメソッドを使って全てのタスクを取得
    tasks := ctrl.GetAll()

    c.HTML(http.StatusOK, "home.tmpl", gin.H{
      "tasks": tasks,
    })
  })

  router.POST("/", func(c *gin.Context) {
    text := c.PostForm("text")

    ctrl := task.NewTask()

    // ControllerのCreateメソッドを使ってタスクを新規作成
    ctrl.Create(text)

    tasks := ctrl.GetAll()

    c.HTML(http.StatusOK, "home.tmpl", gin.H{
      "tasks": tasks,
    })
  })

  router.Run(":8080")
}

controllers/task.go

controllers/task.goはTask構造体作ってそこに各メソッドを突っ込んでる感じですね。

main.goで使うためにNewTask()で作ったTask構造体を使えるようにしています。

メソッドはmodelを通してDBアクセスした結果を返したりしてるだけです。

package task

import (
  "gin-sandbox/models"
)

type Task struct {
}

func NewTask() Task {
  return Task{}
}

// 指定のタスクを取得(今回未使用)
func (c Task) Get(n int) interface{} {
  repo := task.NewTaskRepository()
  task := repo.GetByID(n)
  return task
}

// 全てのタスクを取得
func (c Task) GetAll() interface{} {
  repo := task.NewTaskRepository()
  tasks := repo.GetAll()
  return tasks
}

// タスクを新規作成
func (c Task) Create(text string) {
  repo := task.NewTaskRepository()
  repo.Create(text)
}

models/task.go

models/task.goではDBアクセスを主にやってます。

Repository構造体にDBアクセスを行うメソッドを詰め込んでるって感じですね。

package task

import (
  "github.com/go-xorm/xorm"
  _ "github.com/go-sql-driver/mysql"
)

var engine *xorm.Engine

func init() {
  var err error

  // DBの接続設定
  engine, err = xorm.NewEngine("mysql", "root:@/gin-todo")
  if err != nil {
    panic(err)
  }
}

// DB上のtaskテーブルとマッピング
type Task struct {
  ID  int `json:"id" xorm:"'id'"`
  Text string `json:"text" xorm:"'text'"`
}

// GetAllの時に使用
type Tasks []Task

type TaskRepository struct {
}

func NewTaskRepository() TaskRepository {
  return TaskRepository{}
}

func (m TaskRepository) Create(text string) {
  var task = Task{Text: text}
  engine.Insert(&task)
}

// 今回未使用
func (m TaskRepository) GetByID(id int) *Task {
  var task = Task{ID: id}
  has, _ := engine.Get(&task)
  if has {
    return &task
  }

  return nil
}

func (m TaskRepository) GetAll() Tasks {
  var task = Task{}
  var tasks = Tasks{}
  rows, err := engine.Rows(task)
  if err != nil{
    return nil
  }

  defer rows.Close()
  for rows.Next() {
    err = rows.Scan(&task)
    tasks = append(tasks, task)
  }
  return tasks
}

完成

f:id:syossan:20160311190547p:plain

これでまぁこんな感じの簡素なTODOアプリが出来ました。

あとは色々と肉付けして良い感じに仕上げられたら完璧ですね。