概要
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も試すのもありかな。