Iris(Go言語フレームワーク)の使い方を最速でマスターする
初めに
Iris のマスコットキャラクターらしい(可愛い)
Iris(アイリス)とは何か
Iris はGo言語で書かれたWebフレームワークです.
公式サイトでも『最速のWebフレームワーク』を謳っており,Webサーバ・デスクトップ・スマートフォンなど様々な環境を問わず超高速のパフォーマンスを発揮します
その他の特徴としてクロスプラットフォーム・MVCモデルなどが挙げられます
また,Go言語フレームワークの中でも圧倒的なドキュメント量を実現しており,情報量の多さから最も効率良く学習が出来るともいえます.
実際に,Go言語のwebフレームワークを専門にさまざまな比較を行なっているリポジトリ を参考に他のGoフレームワークと比較してみます
高速性
Iris の最大の特徴は『最速のWebフレームワークである』ということです
他のどのHTTP/2フレームワークよりも高速に動作し,数多くの競合フレームワークと1秒あたりのリクエスト数・転送されたデータ・リクエストとレスポンスの間の時間の測定(ベンチマーク)を実行したところ一番優秀な数値を叩き出しています
Name | Language | Reqs/sec | Latency | Throughput | Time To Complete |
---|---|---|---|---|---|
Iris | Go | 150430 | 826.05us | 41.25MB | 1.33s |
Chi | Go | 146274 | 0.85ms | 39.32MB | 1.37s |
Gin | Go | 141664 | 0.88ms | 38.74MB | 1.41s |
Echo | Go | 138915 | 0.90ms | 38.15MB | 1.44s |
Kestrel | C# | 136935 | 0.91ms | 39.79MB | 1.47s |
Martini | Go | 128590 | 0.97ms | 34.57MB | 1.56s |
Buffalo | Go | 58954 | 2.12ms | 16.18MB | 3.40s |
Koa | JavaScript | 50948 | 2.61ms | 14.15MB | 4.19s |
Express | JavaScript | 38451 | 3.24ms | 13.77MB | 5.21s |
ドキュメント・情報量
Name | Examples | Reference | Real time support |
---|---|---|---|
Iris | 92 | https://github.com/kataras/iris/tree/master/_examples | rocket chat |
Beego | 49 | https://beego.me/docs | |
Echo | 20 | https://echo.labstack.com/cookbook/hello-world | |
Gin | 15 | https://github.com/gin-gonic/gin/tree/master/examples | gitter |
Revel | 6 | http://revel.github.io/examples/index.html | gitter |
Buffalo | 6 | https://gobuffalo.io/docs/installation | slack |
Gin や Echo などの他の競合Goフレームワークと比べて,Iris のドキュメントの量はやはり多いですね
これは私も勉強しながら非常に感じました
機能性
Name | Iris | Beego | Revel | Echo | Gin | Buffalo |
---|---|---|---|---|---|---|
Router: Named Path Parameters & Wildcard* | ※ | |||||
Router: Regex* | ※ | |||||
Router: Grouping* | ❓ | ❓ | ※ | |||
Router: All the above Mixed Without Conflict* | ||||||
Router: Custom HTTP Errors* | ||||||
100% compatible with net/http* | ❓ | |||||
Middleware ecosystem* | ||||||
Sinatra-like API* | ||||||
Server: Automatic HTTPS* | ❓ | |||||
Server: Gracefully Shutdown* | ||||||
Server: Multi Listeners* | ||||||
Full HTTP/2* | ❓ | ❓ | standard | standard | ||
Subdomains* | secondary | secondary | secondary | secondary | secondary | |
Sessions* | secondary | |||||
Websockets* | ||||||
View (aka Templates) Embedded Into App* | ||||||
View Engine: STD* | ||||||
View Engine: Pug* | ||||||
View Engine: Django* | ||||||
View Engine: Handlebars* | ||||||
View Engine: Amber* | ||||||
Renderer: Markdown, JSON, JSONP, XML...* | ||||||
MVC* | ※ | generator | ||||
Caching* | ||||||
File Server* | ||||||
File Server: Embedded Into App* | ||||||
Response can be Modified Many times through lifecycle before sent* | ||||||
Gzip* | middleware | middleware | middleware | |||
Testing Framework* | ||||||
Typescript Transpiler* | ||||||
Online Editor* | ||||||
Logging System* | ※ | ※ | ||||
Maintenance & Auto-Updates* | ||||||
Performance | ★★★★★ | ★★★ | ★★ | ★★★★★ | ★★★★★ | ★★★ |
これまでの表とも合わせて見るに,
他のGoフレームワークに実現できて Iris に実現できないことは全くと言っていいほど無さそうです
準備
早速使っていきましよう
1. まず,Goがインストールされているか以下コマンドにて確認
$ go version
go version go1.17.6
2. Iris をgetしていきます!
// 新規フォルダ作成(既存フォルダにダウンロードする際は不要)
$ mkdir myapp
// Iris をダウンロードしたいフォルダに移動
$ cd myapp
// go mod 初期化
$ go mod init myapp
// Irisのパッケージ取得
$ go get github.com/kataras/iris/v12@master
// go のバージョンが 1.17 以降
$ go install github.com/kataras/iris/v12@latest
Iris の基本編
Iris を使って簡単なAPIを作成してみます(※ MVCにしない場合)
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
app.Handle("GET", "/", func(ctx iris.Context) {
ctx.JSON(iris.Map{"message": "ping"})
})
app.Listen(":8080")
}
go run main.go
でサーバーを立ち上げて localhost:8080
にアクセスしてみると,
Jsonメッセージの {"message":"ping"}
が返ります
もしもフレームワーク等を使わずに素のGoで同じサーバーを作る場合,以下のようになります 👇
package main
import (
"encoding/json"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, q *http.Request) {
message := map[string]string{
"message": "ping",
}
jsonMessage, err := json.Marshal(message)
if err != nil {
panic(err.Error())
}
w.Write(jsonMessage)
})
http.ListenAndServe("127.0.0.1:8080", mux)
}
コードの量がほぼ倍になりました...
この理由を見てみましょう
// Context is the midle-man server's "object" dealing with incoming requests.
//
// A New context is being acquired from a sync.Pool on each connection.
// The Context is the most important thing on the iris's http flow.
//
// Developers send responses to the client's request through a Context.
// Developers get request information from the client's request a Context.
type Context struct {
// the http.ResponseWriter wrapped by custom writer.
writer ResponseWriter
// the original http.Request
request *http.Request
// the current route registered to this request path.
currentRoute RouteReadOnly
// the local key-value storage
params RequestParams // url named parameters.
values memstore.Store // generic storage, middleware communication.
query url.Values // GET url query temp cache, useful on many URLParamXXX calls.
// the underline application app.
app Application
// the route's handlers
handlers Handlers
// the current position of the handler's chain
currentHandlerIndex int
// proceeded reports whether `Proceed` method
// called before a `Next`. It is a flash field and it is set
// to true on `Next` call when its called on the last handler in the chain.
// Reports whether a `Next` is called,
// even if the handler index remains the same (last handler).
//
// Also it's responsible to keep the old value of the last known handler index
// before StopExecution. See ResumeExecution.
proceeded int
// if true, caller is responsible to release the context (put the context to the pool).
manualRelease bool
}
つまり,素のGoで HandleFunc
を書く際にパラメータとして存在する http.ResponseWriter
や http.Request
が,Iris の Context構造体(struct)
の構成要素として格納されていて,それが関数の内部で使用されているという仕組みです
ちなみに,app.Listen(":8080")
も実際には http.ListenAndServe(address, engine)
などが中身で呼ばれています
元々のGoのコードを活かして便利な処理を実現していることが分かります!
ミドルウェアの使用
リクエストに対する処理は基本下記のようになります
Request -> Route Parser -> Middleware -> Route Handler -> Middleware -> Response
つまり,実際に処理を行う関数に到達する前に必ずミドルウェアを通る必要があります
上記でのmain.goに合わせて使うとこんな感じです 👇
ポイントは,『ミドルウェアは実装の前で使用する』 ということです
package main
import (
"net/http"
"github.com/kataras/iris/v12"
)
func main() {
app := iris.New()
// こんな感じで
// 実装の前の部分で使用!!!!!
app.WrapRouter(routerWrapper)
app.UseRouter(routerMiddleware)
app.UseGlobal(globalMiddleware)
app.Use(useMiddleware)
app.UseError(errorMiddleware)
app.Done(done)
app.DoneGlobal(doneGlobal)
app.Handle("GET", "/", func(ctx iris.Context) {
ctx.JSON(iris.Map{"message": "ping"})
})
// 以下 様々な処理等...
app.Listen(":8080")
}
Iris ではミドルウェアが豊富にあり,それらを覚えきるのは大変なので...
まずは「ふむふむこんな感じで使えばいいんやね〜〜」と覚えておいてください.
(業務で使うとなるとミドルウェア一つ一つ覚えていく必要は,やはりあります)
HTMLや静的ファイルを表示する
HTMLファイルを表示する
超簡単です
app.RegisterView()
という Iris の組み込み関数を使い,表示用ディレクトリとその中のどの種類のファイル(.html
など)を表示するかを指定して,あとはURLによって表示したいHTMLファイルを指定していくだけです
実際に見てみましょう
ディレクトリ構造は以下の想定です ※
myapp
|- public
|- |- books
|- |- |- list.html
|- |- |- purchase.html
|- go.mod
|- main.go
コードはこんな感じです 👇
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
// "public" ディレクトリ配下の ".htmlファイル" を返却するように設定
// 上書きされバグが潜む可能性があるため基本的には一度だけ設定するようにし,
// 指定したディレクトリ(今回は "public")配下にディレクトリを増やしていくようにする
app.RegisterView(iris.HTML("/public", ".html"))
// GET: "/"
app.Get("/", func(ctx iris.Context) {
// 返却するviewファイルの指定("/public" フォルダからのパス)
ctx.View("index.html")
})
// "/books/"から始まるURLを受け取った際の処理をグループ化
books := app.Party("/books")
{
// GET: "/books/"
books.Get("/", func(ctx iris.Context) {
// "/public" フォルダからのパスで指定
ctx.View("/books/list.html")
})
// GET: "/books/buy"
books.Get("/buy", func(ctx iris.Context) {
// "/public" フォルダからのパスで指定
ctx.View("/books/purchase.html")
})
}
app.Listen(":8080")
}
サーバーを立ち上げて localhost:8080
にアクセスすると,public/index.html
の内容が確認できるはずです
localhost:8080/books/buy
にアクセスしても public/books/index.html
の内容が確認できるはずです.
静的ファイルを表示する
これも簡単です
app.HandleDir("受け取るURL", iris.Dir("表示したいファイルや画像があるディレクトリまでのパス"))
と書くだけです
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
// 静的ファイルの表示
// "public" フォルダ以下のファイルが表示される
app.HandleDir("/", iris.Dir("/public"))
// 以下 様々な処理等...
app.Listen(":8080")
}
サーバーを立ち上げて localhost:8080
をアクセスすると public
ディレクトリ以下の任意のファイルや画像が表示されるはずです.
ファイルのアップロード
Iris としては
ctx.SaveFormFile(ファイル, 保存先までのパス)
といった機能などが備わっています
コードで見た方が早いと思います 👇
const maxSize = 8 * iris.MB
func main() {
app := iris.Default()
app.Post("/upload", func(ctx iris.Context) {
// ファイルの最大容量はあらかじめ決めておいてもいいかもしれません
ctx.SetMaxRequestBodySize(maxSize)
// 👆 はミドルウェアでも指定できます
// app.Use(iris.LimitRequestBodySize(maxSize))
// または
// iris.WithPostMaxMemory(maxSize) なども
file, fileHeader, err:= ctx.FormFile("file")
if err != nil {
ctx.StopWithError(iris.StatusBadRequest, err)
return
}
// 保存先を作っておく
// ここでは "destination" に "./public/ファイル名" というパスが文字列で格納される
destination := filepath.Join("./public", fileHeader.Filename)
// 保存処理
ctx.SaveFormFile(fileHeader, destination)
})
app.Listen(":8080")
}
リクエストからクエリ / パラメータを取得(Get, Post, Put, Delete...)
こちらも Iris に備え付きの機能を使用すれば簡単です
クエリ取得
ctx.ReadQuery()
ctx.URLParamInt()
パラメータ取得
ctx.Params().Get()
など...
クエリ取得
package main
import "github.com/kataras/iris/v12"
type MyType struct {
// "url" タグでクエリ名を指定しています
Name string `url:"name,required"`
Age int `url:"age"`
}
func main() {
app := iris.New()
// GET: "localhost:8080/users?name=tom&?age=19"
// パターン 1.
app.Handle("GET", "/users", func(ctx iris.Context) {
var t MyType
// クエリがある場合,iris.Context の機能を使って以下のように取得できます
// ここではクエリから受け取ったデータを構造体(struct)に格納しています
err := ctx.ReadQuery(&t)
//「t」を使った様々な処理等...
})
// もちろんメソッドへの切り出しもできます
app.Handle("GET", "/users", getUser)
func getUser(ctx iris.Context) {
// 以下略
}
// パターン 2.
app.Handle("GET", "/users", func(ctx iris.Context) {
// iris.Context の機能を使って以下のようにも取得できます
// "name" と言うクエリを取得し,変数に格納しています
name, err := c.Ctx.URLParamInt("name") // name => "Tom"
// 「name」を使った様々な処理等...
})
app.Listen(":8080")
}
パラメータ取得
package main
import "github.com/kataras/iris/v12"
func main() {
app := iris.New()
// GET: "localhost:8080/users/123(IDなど)"
// パターン 1.
app.Handle("GET", "/users/{id:int}", func(ctx iris.Context) {
// iris.Context の機能を使ってこのように取得できます
id, _ := ctx.Params().Get("id")
// 「id」を使った様々な処理等...
})
// もちろんメソッドへの切り出しもできます
app.Handle("GET", "/users/{id:int}", getUser)
func getUser(ctx iris.Context) {
// 以下略
}
// パターン 2.
app.Handlefunc("PUT", "/users/{id:int}", updateUser)
func updateUser(id int) response {
// こう書くだけで,もうパラメータの「id」が引数として取得できています
// 「id」を使った様々な処理等...
})
}
Iris でMVCモデルの簡単なAPIを作ってみよう
最初に説明
今回は以下の機能を実装しようと思います
実装機能
ユーザーの
- 新規作成
- POST: http://localhost:8080/users (※ jsonのリクエストボディにてデータを送る)
- 一覧取得
- 更新
- 削除
さて,基本編で作成したAPIは,main.go
の中にあくまで受け取りたいパスやその後の処理などを”ベタ書き”したものに過ぎず,Iris のパフォーマンスを活かしきれているとは言えません
今回は Iris の強みを活かして,MVCモデルを形成しながらAPIを作っていきたいと思います
ディレクトリ構成
example-mvc-api
|- controller
|- |- users
|- |- |- users_controller.go
|- setups
|- |- configure_users_controllers.go // DI(依存性注入)を行う部分
|- model
|- |- user.go
|- service
|- |- user.go
|- |- init.go
|- go.mod
|- main.go
必要なパッケージをgetします(Iris は既にgetできている想定)
また,今回DBとのやりとりを行うためのORMに関しては gorp
パッケージを使用してます − 公式リポジトリ
$ go get github.com/go-sql-driver/mysql
$ go get github.com/go-gorp/gorp
// go 1.17 以降
$ go install github.com/go-sql-driver/mysql@latest
$ go install github.com/go-gorp/gorp@latest
main.go
package main
import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/middleware/accesslog"
"github.com/kataras/iris/v12/middleware/recover"
"github.com/kataras/iris/v12/mvc"
"go-iris-sample/setups"
)
func main() {
app := iris.New()
// ミドルウェアの使用
app.Use(iris.Compression)
app.Configure(iris.WithoutBodyConsumptionOnUnmarshal)
// ログ記録(これも備え付きミドルウェア)
ac := accesslog.File("./access.log")
defer ac.Close()
app.UseRouter(ac.Handler)
app.UseRouter(recover.New())
// "/users/"から始まるURLを受け取った際の処理をグループ化
users := app.Party("/users")
mvc.Configure(users, setups.ConfigureUsersControllers)
// ポートの指定
app.Listen(":8080")
}
setups/configure_users_controllers.go(※ DI - 依存性注入 を行う)
Iris でMVCモデルを形成するためには,main.go
で作ったパスのグループ(を表す変数など)に対して,使用する controller などを DI(依存性注入)を行う必要がありますが,今回はそれをこの setups
ディレクトリで行なっています(ディレクトリの名前は何でも大丈夫です)
具体的なところはコードを見てください
import (
"github.com/kataras/iris/v12/middleware/accesslog"
"github.com/kataras/iris/v12/mvc"
"go-iris-sample/controller/users"
)
// ConfigureUsersControllers
// main.go で定義したURLのグループを表す変数(ここではusers)が引数に入り,
// それに対してDI(依存性注入)を行っている
func ConfigureUsersControllers(app *mvc.Application) {
// ログを取得してくれる機能のDIもここで行う
app.Register(accesslog.GetFields)
// URLが "/users" から始まるリクエストを受け取った際に,
// 以下の Controllerを使用させるという指示
app.Handle(new(users.UsersController))
}
controller/users/users_controller.go(※ ここがポイント!!!!)
さて,main.go
で users
から始まるパスのグループを作りましたが,ここで今回のAPIのエンドポイント(受け取るURL)を再び確認してみましょう
- ~/users
- ~/users/list
- ~/users/details/{id:uint}
- ~/users/details/{id:uint}
どれも /users/
からURLが始まりますが,/users/list
や /users/details
... などのようにURLは分岐しています
これをどう実装しましょう.
基礎編で書いたコードのように,また他のGoフレームワークではそうですが....
app.Get("GET", "/users/list", ...)
といった具合に,メソッドや一つ一つのパスを”ベタ書き”したような関数をたくさん作っていくのでは大変です
そもそも,「関数」のことを controller とするのは美しいMVC形成と言えません(機能の分割などが困難で小回りが利かない・一つの関数に書く量が多くなっていくのは保守性が低い) ❌
また,例えばRailsなど他のフレームワークのようにルーティングについてまとめたファイルも Iris では書きません ❌
もっといい方法があります!Iris には『MVCモデルを形成するためだけの機能』がたくさんあるので,そちら使いましょう
正解は...
『コントローラー(controller)のメソッドの名前を変える』だけ
です! ✅
これが超便利なんです
具体的に説明します!
まず,main.go
などでURLのグルーピングをします(今回は "~/users"
).
その上で,例えば GET で /users/list
というURLを受け取る際の処理を行うには,関連する controllerに GetList()
というメソッドを,
POST で /users/details
というURLを受け取る際の処理を行うには,controllerに PostDetails()
というメソッドを作りその中に処理を書いていく.....(※ パラメータやクエリについては,そこまでは書かなくて大丈夫です)
といった具合に,受け取る想定のURLの,app.Party()
などで最初に指定された部分(ここでは users
)以降の部分をキャメルケースでcontrollerのメソッドの名前にすれば, それを Iris が自動で判別してそのメソッドを自動で行なってくれるのです!
つまりこの場合,
- GET で
/users/list
というURLでリクエストがきた場合,Iris が自動でそれを判別してcontrollerのGetList()
という名前のメソッドの処理が行われる - POST で
/users/details
というURLでリクエストがきた場合,Iris が自動でそれを判別してcontrollerのPostDetails()
という名前のメソッドの処理が行われる
となります
(※ users := app.Party("/users")
などとしてURLのグルーピングされている・DIされている前提)
ですので,例えば今回 GET で users/users/users/
というURLも受け取る場合,controllerに GetUsersUsers()
という名前のメソッドがあればもちろんそのメソッドの処理が行われます
実際にコードを見てみましょう 👇
ここでの機能としては,上記の通りリクエスト毎に controller のメソッドを判別 -> 処理を service にハンドル -> レスポンスを返す となっています
package users
import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/mvc"
"go-iris-sample/model"
"go-iris-sample/service"
)
type UsersController struct {
UserService service.UserService
Ctx iris.Context
}
// メソッド名でパスの違い・リクエストメソッド・パラメータを受け付けます(超便利)
// [例]
// GetList() GET: "http://localhost:8080/users/list"
// Post() POST: "http://localhost:8080/users"
// PutDetails() PUT: "http://localhost:8080/users/details"
// PutDetailsBy(id uint) PUT: "http://localhost:8080/users/details/{id:int}"
// DeleteDetails() DELETE: "http://localhost:8080/users/details"
// DeleteDetailsBy(id uint) DELETE: "http://localhost:8080/users/details/{id:int}"
// [その他の例]
// POST: http://localhost:8080/users/details/example -> PostDetailsExample()
// PUT: http://localhost:8080/users -> Put()
func (c *UsersController) GetList() mvc.Response {
// 一覧取得
users, err := c.UserService.GetUserList()
if err != nil {
return mvc.Response{
Code: iris.StatusInternalServerError, // エラーハンドリング
}
}
// Iris に備え付きのレスポンス用構造体(struct)
return mvc.Response{
Code: iris.StatusOK,
Object: users,
}
}
func (c *UsersController) Post() mvc.Response {
// リクエストボディのjsonデータを構造体(struct)に格納する
var user model.User
err := c.Ctx.ReadJSON(&user)
// エラーハンドリング(Iris 備え付きのもので作れます)
if err != nil {
c.Ctx.StopWithError(iris.StatusBadRequest, err)
return mvc.Response{
Code: iris.StatusBadRequest,
}
}
// 新規作成
err = c.UserService.CreateUser(&user)
if err != nil {
return mvc.Response{
Code: iris.StatusInternalServerError, // エラーハンドリング
}
}
// Iris 備え付きのレスポンス用構造体(struct)
return mvc.Response{ Code: iris.StatusCreated }
}
func (c *UsersController) PutDetailsBy(id int) mvc.Response {
// リクエストボディのjsonデータを構造体(struct)に格納する
var user model.User
err := c.Ctx.ReadJSON(&user)
// エラーハンドリング(Iris 備え付きのもので作れます)
if err != nil {
c.Ctx.StopWithError(iris.StatusBadRequest, err)
return mvc.Response{
Code: iris.StatusBadRequest,
}
}
user.Id = id
// 更新
err = userService.UpdateUser(&user)
if err != nil {
return mvc.Response{
Code: iris.StatusInternalServerError, // エラーハンドリング
}
}
// Iris 備え付きのレスポンス用構造体(struct)
return mvc.Response{ Code: iris.StatusOK }
}
func (c *UsersController) DeleteDetailsBy(id int) mvc.Response {
// 削除
err := c.UserService.DeleteUser(id)
if err != nil {
return mvc.Response{
Code: iris.StatusInternalServerError, // エラーハンドリング
}
}
// Iris 備え付きのレスポンス用構造体(struct)
return mvc.Response{ Code: iris.StatusOK }
}
model/user.go
User構造体(struct)を定義しています
db
タグをつけておくことで,ORMを使ってDBとやりとりできます
package model
type User struct {
Id string `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Age uint32 `json:"age" db:"age"`
}
service/init.go
データベースへの接続とテーブルの初期化を実装します
package service
import (
"database/sql"
"fmt"
"github.com/go-gorp/gorp"
"go-iris-sample/model"
"log"
"os"
_ "github.com/go-sql-driver/mysql"
)
// gorp初期化処理
func InitDb() *gorp.DbMap {
dbUserName := "DB_USERNAME"
dbPassWord := "DB_PASSWORD"
dbHost := "DB_HOST"
dbPort := "DB_PORT"
dbDbName := "DB_DBNAME"
db, err := sql.Open("mysql", fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?parseTime=true", dbUserName, dbPassWord, dbHost, dbPort, dbDbName))
if err != nil {
fmt.Printf("error! can't open sql driver %v", err)
}
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}}
// テーブル作成
dbmap.AddTableWithName(model.User{}, "user").SetKeys(true, "Id")
err = dbmap.CreateTablesIfNotExists()
if err != nil {
fmt.Printf("error! can't craete table: %v", err)
}
// ログの取得
dbmap.TraceOn("[gorp]", log.New(os.Stdout, "go-iris-sample:", log.Lmicroseconds))
return dbmap
}
service/user.go
実装の部分です
ここではコントローラからハンドリングされた以下の処理を行います
ユーザーの
-
一覧取得
-
新規作成
-
更新
-
削除
を行っています
package service
import (
"go-iris-sample/_example-mvc-api/model"
_ "github.com/go-sql-driver/mysql"
)
type UserService struct {}
func (UserService) GetUserList() ([]model.User, error) {
// initialize the DbMap
dbMap := InitDb()
defer dbMap.Db.Close()
var users []model.User
// ユーザーを全取得
_, err := dbMap.Select(&users, `SELECT * FROM users`)
if err != nil {
return []model.User{}, err
}
return users, nil
}
func (UserService) CreateUser(user *model.User) error {
// initialize the DbMap
dbMap := InitDb()
defer dbMap.Db.Close()
// トラン ザクションを走らせながらinsert
tx, _ := dbMap.Begin()
err := tx.Insert(user)
if err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
func (UserService) UpdateUser(user *model.User) error {
// initialize the DbMap
dbMap := InitDb()
defer dbMap.Db.Close()
// トランザクションを走らせながらupdate
tx, _ := dbMap.Begin()
_, err := tx.Update(user)
if err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
func (UserService) DeleteUser(id int) error {
// initialize the DbMap
dbMap := InitDb()
defer dbMap.Db.Close()
// id から削除するユーザーを取得
var user model.User
err := dbMap.SelectOne(&user, `SELECT * FROM users WHERE id = :id`,
map[string]interface{}{
"id": id,
})
if err != nil {
fmt.Printf("error! can't find user by id: %v.\n", id)
return err
}
// トランザクションを走らせながらdelete
tx, _ := dbMap.Begin()
_, err := tx.Delete(&user)
if err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
こんな感じで,Iris を使ってAPIを作れます
go run main.go
でサーバーを立ち上げて,それぞれのエンドポイントにリクエスト内容を正しい内容にしてアクセスし,正常に動作することを確認してください
また,以下は例ですが,起動後URLへアクセスをするとこんな感じのログも確認できるはずかと思います
2022-04-17 19:08:16|1.19426ms|200|GET|/|::1|0 B|10 B||
2022-04-17 19:08:16|42.803µs|404|GET|/favicon.ico|::1|0 B|0 B||
2022-04-17 19:08:21|27.538µs|404|GET|/favicon.ico|::1|0 B|0 B||
2022-04-17 19:09:36|112.584µs|404|GET|/favicon.ico|::1|0 B|0 B||
2022-04-17 19:09:40|32.466µs|404|GET|/favicon.ico|::1|0 B|0 B||
2022-04-17 19:09:44|180.006µs|200|GET|/|::1|0 B|10 B||
2022-04-17 19:09:44|25.901µs|404|GET|/favicon.ico|::1|0 B|0 B||
2022-04-17 19:09:58|168.375µs|200|GET|/users|::1|0 B|10 B||
2022-04-17 19:09:58|29.095µs|404|GET|/favicon.ico|::1|0 B|0 B||
2022-04-17 19:10:47|322.583µs|200|GET|/users|127.0.0.1|64 B|10 B|{"firstname":"Tanaka","lastname":"ryo","age":15}|
長くなってしまいましたが,以上になります.
終わりに
これまでも述べてきたように,Iris はGo言語のつよつよフレームワークです
ぜひ一度使ってみてください!
参考記事
大感謝です 🙇🏼♂️
Author And Source
この問題について(Iris(Go言語フレームワーク)の使い方を最速でマスターする), 我々は、より多くの情報をここで見つけました https://zenn.dev/mkosakana/articles/3c80695d63e127著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol