package main import ( "fmt" "time" "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/mvc" ) func main() { app := iris.New() app.RegisterView(iris.HTML("./views", ".html")) m := mvc.New(app) m.Handle(new(controller)) app.Listen(":8080") } type controller struct{} // Generic response type for JSON results. type response struct { ID uint64 `json:"id,omitempty"` Data interface{} `json:"data,omitempty"` // {data: result } on fetch actions. Code int `json:"code,omitempty"` Message string `json:"message,omitempty"` Timestamp int64 `json:"timestamp,omitempty"` } func (r response) Preflight(ctx iris.Context) error { if r.ID > 0 { r.Timestamp = time.Now().Unix() } if code := r.Code; code > 0 { // You can call ctx.View or mvc.Vew{...}.Dispatch // to render HTML on Code != 200 // but in order to not proceed with the response resulting // as JSON you MUST return the iris.ErrStopExecution error. // Example: if code != 200 { mvc.View{ /* calls the ctx.StatusCode */ Code: code, /* use any r.Data as the template data OR the whole "response" as its data. */ Data: r, /* automatically pick the template per error (just for the sake of the example) */ Name: fmt.Sprintf("%d", code), }.Dispatch(ctx) return iris.ErrStopExecution } ctx.StatusCode(r.Code) } return nil } type user struct { ID uint64 `json:"id"` } func (c *controller) GetBy(userid uint64) response { if userid != 1 { return response{ Code: iris.StatusNotFound, Message: "User Not Found", } } return response{ ID: userid, Data: user{ID: userid}, } } /* You can use that `response` structure on non-mvc applications too, using handlers: c := app.ConfigureContainer() c.Get("/{id:uint64}", getUserByID) func getUserByID(id uint64) response { if userid != 1 { return response{ Code: iris.StatusNotFound, Message: "User Not Found", } } return response{ ID: userid, Data: user{ID: userid}, } } */