5
4

More than 3 years have passed since last update.

GolangでシンプルなRESTful APIを作ってみた

Last updated at Posted at 2019-12-07

概要

GoでシンプルなRESTful APIを作りました。
簡単にしたかったので読み出しの機能のみです。

サンプルはここ

環境

  • go 1.13.4
  • mysql 8.0.17

Framework

Hello World!

  • hogeリポジトリを作る
  • プロジェクトを作成
$ mkdir hoge
$ cd hoge
$ go mod init github.com/<owner>/hoge

go modについては以下参照
Package Management With Go Modules

echoを依存関係に追加

$ go get -u github.com/labstack/echo/...

main.goを作成

package main

import (
    "net/http"

    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })
    e.Logger.Fatal(e.Start(":1323"))
}

サーバを起動

$ go run main.go
$ curl http://127.0.0.1:1323/
Hello, World!

ユーザを取得するAPIを作成する

以下のAPIを作成する

  • /users -> userのリスト、userデータを全部返す
  • /users/{id} -> idに紐づくuserの情報を返す
...
func main() {
    e := echo.New()
    e.GET("/users", GetUsers)
    e.GET("/users/:id", GetUser)

    e.Logger.Fatal(e.Start(":1323"))
}

type User struct {
    ID   int
    Name string
}

func GetUsers(c echo.Context) error {
    var users []User
    return c.JSON(http.StatusOK, users)
}

func GetUser(c echo.Context) error {
    userid, err := strconv.Atoi(c.Param("id"))
    if err != nil {
        return err
    }
    user := &User{
        ID:   userid,
        Name: "dummy",
    }
    return c.JSON(http.StatusOK, user)
}

サーバを起動する

$ curl http://127.0.0.1:1323/users
null

$ curl http://127.0.0.1:1323/users/1
{"ID":1,"Name":"dummy"}

MySQLに接続する

mysqlを依存関係に追加

$ go get github.com/go-sql-driver/mysql

DB名: sample
テーブル名: users

id name
1 suzuki
2 takahashi
3 tanaka

db接続

  db, err := sql.Open("mysql", "root@/gosample")
  if err != nil {
    panic(err.Error())
  }
  defer db.Close()

データ取得

  rows, err := db.Query("SELECT * FROM users")
  defer rows.Close()
  if err != nil {
    return []User{}, err
  }

サーバを起動する

$ curl http://127.0.0.1:1323/users
[{"ID":1,"Name":"suzuki"},{"ID":2,"Name":"takahashi"},{"ID":3,"Name":"tanaka"}]

$ curl http://127.0.0.1:1323/users/1
{"ID":1,"Name":"suzuki"}

main.go

package main

import (
    "database/sql"
    "net/http"
    "strconv"

    _ "github.com/go-sql-driver/mysql"
    "github.com/labstack/echo"
)

var connection *sql.DB

func main() {
    db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/sample")
    if err != nil {
        panic(err.Error())
    }
    connection = db
    defer db.Close()

    e := echo.New()
    e.GET("/users", GetUsers)
    e.GET("/users/:id", GetUser)

    e.Logger.Fatal(e.Start(":1323"))
}

type User struct {
    ID   int
    Name string
}

func GetUsers(c echo.Context) error {
    users, err := FindAll(connection)
    if err != nil {
        return err
    }
    return c.JSON(http.StatusOK, users)
}

func GetUser(c echo.Context) error {
    userid, err := strconv.Atoi(c.Param("id"))
    if err != nil {
        return err
    }
    user, err := FindById(connection, userid)
    if err != nil {
        return err
    }
    return c.JSON(http.StatusOK, user)
}

func FindAll(db *sql.DB) ([]User, error) {
    rows, err := db.Query("SELECT * FROM users")
    defer rows.Close()
    if err != nil {
        return []User{}, err
    }

    var users []User
    for rows.Next() {
        var user User
        if err := rows.Scan(&user.ID, &user.Name); err != nil {
            return []User{}, err
        }
        users = append(users, user)
    }

    return users, nil
}

func FindById(db *sql.DB, id int) (User, error) {
    rows, err := db.Query("SELECT * FROM users WHERE id = ?", id)
    defer rows.Close()
    if err != nil {
        return User{}, err
    }

    rows.Next()
    var user User
    if err := rows.Scan(&user.ID, &user.Name); err != nil {
        return User{}, err
    }
    return user, nil
}

まとめ

今回はGETの実装のみで終わってしまいましたが、その他のメソッドについても実装したいです。
ORMも試すのもありかな。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4