Go 框架 iris 文档(一)

简介: Go 框架 iris 文档(一)

安装

Iris是一个跨平台的软件。

唯一的要求是 Go 编程语言,版本 1.20 及更高版本。

$ mkdir myapp
$ cd myapp
$ go mod init myapp
$ go get github.com/kataras/iris/v12@latest

将其导入到代码中:

import "github.com/kataras/iris/v12"

故障 排除

如果在安装过程中遇到网络错误,请确保设置了有效的 GOPROXY 环境变量

go env -w GOPROXY=https://goproxy.io,direct

如果上述方法均无效,请清理 go 模块缓存:

go clean --modcache

快速入门

# assume the following codes in main.go file
$ cat main.go
package main
import "github.com/kataras/iris/v12"
func main() {
    app := iris.New()
    booksAPI := app.Party("/books")
    {
        booksAPI.Use(iris.Compression)
        // GET: http://localhost:8080/books
        booksAPI.Get("/", list)
        // POST: http://localhost:8080/books
        booksAPI.Post("/", create)
    }
    app.Listen(":8080")
}
// Book example.
type Book struct {
    Title string `json:"title"`
}
func list(ctx iris.Context) {
    books := []Book{
        {"Mastering Concurrency in Go"},
        {"Go Design Patterns"},
        {"Black Hat Go"},
    }
    ctx.JSON(books)
    // TIP: negotiate the response between server's prioritizes
    // and client's requirements, instead of ctx.JSON:
    // ctx.Negotiation().JSON().MsgPack().Protobuf()
    // ctx.Negotiate(books)
}
func create(ctx iris.Context) {
    var b Book
    err := ctx.ReadJSON(&b)
    // TIP: use ctx.ReadBody(&b) to bind
    // any type of incoming data instead.
    if err != nil {
        ctx.StopWithProblem(iris.StatusBadRequest, iris.NewProblem().
            Title("Book creation failure").DetailErr(err))
        // TIP: use ctx.StopWithError(code, err) when only
        // plain text responses are expected on errors.
        return
    }
    println("Received Book: " + b.Title)
    ctx.StatusCode(iris.StatusCreated)
}

MVC 等效项:

import "github.com/kataras/iris/v12/mvc"
m := mvc.New(booksAPI)
m.Handle(new(BookController))
type BookController struct {
    /* dependencies */
}
// GET: http://localhost:8080/books
func (c *BookController) Get() []Book {
    return []Book{
        {"Mastering Concurrency in Go"},
        {"Go Design Patterns"},
        {"Black Hat Go"},
    }
}
// POST: http://localhost:8080/books
func (c *BookController) Post(b Book) int {
    println("Received Book: " + b.Title)
    return iris.StatusCreated
}

运行您的鸢尾花网络服务器:

$ go run main.go
> Now listening on: http://localhost:8080
> Application started. Press CTRL+C to shut down.

列表书:

$ curl --header 'Accept-Encoding:gzip' http://localhost:8080/books
[
  {
    "title": "Mastering Concurrency in Go"
  },
  {
    "title": "Go Design Patterns"
  },
  {
    "title": "Black Hat Go"
  }
]

创建新图书:

$ curl -i -X POST \
--header 'Content-Encoding:gzip' \
--header 'Content-Type:application/json' \
--data "{\"title\":\"Writing An Interpreter In Go\"}" \
http://localhost:8080/books
> HTTP/1.1 201 Created

这就是错误响应的样子:

$ curl -X POST --data "{\"title\" \"not valid one\"}" \
http://localhost:8080/books
> HTTP/1.1 400 Bad Request
{
  "status": 400,
  "title": "Book creation failure"
  "detail": "invalid character '\"' after object key",
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NL5y3Dps-1686647378212)(null)]

基准

Iris使用muxie的自定义版本。

查看所有基准

📖 使用 int 的动态参数触发 200000 个请求,将 JSON 作为请求正文发送,并接收 JSON 作为响应。

名字 语言 要求/秒 延迟 吞吐量 完成时间
虹膜 238954 521.69乌秒 64.15兆字节 0.84秒
琴酒 229665 541.96乌秒 62.86兆字节 0.87秒
228072 545.78乌秒 62.61兆字节 0.88秒
回波 224491 553.84乌秒 61.70兆字节 0.89秒
马提尼酒 198166 627.46乌秒 54.47兆字节 1.01秒
茶隼 C# 163486 766.90乌秒 47.42兆字节 1.23秒
水牛 102478 1.22毫秒 28.14兆字节 1.95秒
科阿 爪哇语 48425 2.56毫秒 15.39兆字节 4.14秒
表达 爪哇语 23622 5.25毫秒 9.04兆字节 8.41秒

接口示例

您可以在 Iris 示例存储库中找到许多随时可以运行的示例。

使用获取、发布、放置、修补、删除和选项

func main() {
    // Creates an iris application with default middleware:
    // Default with "debug" Logger Level.
    // Localization enabled on "./locales" directory
    // and HTML templates on "./views" or "./templates" directory.
    // It runs with the AccessLog on "./access.log",
    // Recovery (crash-free) and Request ID middleware already attached.
    app := iris.Default()
    app.Get("/someGet", getting)
    app.Post("/somePost", posting)
    app.Put("/somePut", putting)
    app.Delete("/someDelete", deleting)
    app.Patch("/somePatch", patching)
    app.Header("/someHead", head)
    app.Options("/someOptions", options)
    app.Listen(":8080")
}

路径中的参数

func main() {
    app := iris.Default()
    // This handler will match /user/john but will not match /user/ or /user
    app.Get("/user/{name}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        ctx.Writef("Hello %s", name)
    })
    // However, this one will match /user/john/ and also /user/john/send
    // If no other routers match /user/john, it will redirect to /user/john/
    app.Get("/user/{name}/{action:path}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        action := ctx.Params().Get("action")
        message := name + " is " + action
        ctx.WriteString(message)
    })
    // For each matched request Context will hold the route definition
    app.Post("/user/{name:string}/{action:path}", func(ctx iris.Context) {
        ctx.GetCurrentRoute().Tmpl().Src == "/user/{name:string}/{action:path}" // true
    })
    app.Listen(":8080")
}

内置可用参数类型:

参数类型 去类型 验证 检索帮助程序
:string 字符串 任何(单路径段) Params().Get
:uuid 字符串 uuidv4 或 v1(单路径段) Params().Get
:int 国际 -9223372036854775808 到 9223372036854775807 (x64) 或 -2147483648 到 2147483647 (x32),取决于主机架构 Params().GetInt
:int8 国际8 -128 到 127 Params().GetInt8
:int16 国际16 -32768 到 32767 Params().GetInt16
:int32 国际32 -2147483648 到 2147483647 Params().GetInt32
:int64 国际64 -9223372036854775808 到 9223372036854775807 Params().GetInt64
:uint 乌因特 0 到 18446744073709551615 (x64) 或 0 到 4294967295 (x32),取决于主机架构 Params().GetUint
:uint8 uint8 0 到 255 Params().GetUint8
:uint16 uint16 0 到 65535 Params().GetUint16
:uint32 uint32 0 到 4294967295 Params().GetUint32
:uint64 uint64 0 到 18446744073709551615 Params().GetUint64
:bool 布尔 “1”或“t”或“T”或“真”或“真”或“真”或“0”或“f”或“F”或“假”或“假”或“假” Params().GetBool
:alphabetical 字符串 小写或大写字母 Params().Get
:file 字符串 小写或大写字母、数字、下划线 (_)、短划线 (-)、点 (.) 并且没有空格或其他对文件名无效的特殊字符 Params().Get
:path 字符串 任何内容都可以用斜杠(路径段)分隔,但应该是路由路径的最后一部分 Params().Get
:mail 字符串 未经域验证的电子邮件 Params().Get
:email 字符串 具有域验证功能的电子邮件 Params().Get
:date 字符串 年/月/日格式,例如 /博客/{参数:日期} 匹配 /博客/2022/04/21 Params().GetTimeParams().SimpleDate
:weekday uint (0-6) 或字符串 时间串。工作日长名称格式(“星期日”到“星期一”或“星期日”到“星期一”)格式,例如 /schedule/{param:weekday} 匹配 /schedule/星期一 Params().GetWeekday

更多示例可在以下位置找到:_examples/路由

查询字符串参数

func main() {
    app := iris.Default()
    // Query string parameters are parsed using the existing underlying request object.
    // The request responds to a url matching:  /welcome?firstname=Jane&lastname=Doe
    app.Get("/welcome", func(ctx iris.Context) {
        firstname := ctx.URLParamDefault("firstname", "Guest")
        lastname := ctx.URLParam("lastname") // shortcut for ctx.Request().URL.Query().Get("lastname")
        ctx.Writef("Hello %s %s", firstname, lastname)
    })
    app.Listen(":8080")
}

多部分/乌伦编码形式

func main() {
    app := iris.Default()
    app.Post("/form_post", func(ctx iris.Context) {
        message := ctx.PostValue("message")
        nick := ctx.PostValueDefault("nick", "anonymous")
        ctx.JSON(iris.Map{
            "status":  "posted",
            "message": message,
            "nick":    nick,
        })
    })
    app.Listen(":8080")
}

再比如:查询+帖子表单

POST /post?id=1234&page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
name=kataras&message=this_is_great
func main() {
    app := iris.Default()
    app.Post("/post", func(ctx iris.Context) {
        id, err := ctx.URLParamInt("id", 0)
        if err != nil {
            ctx.StopWithError(iris.StatusBadRequest, err)
            return
        }
        page := ctx.URLParamIntDefault("page", 0)
        name := ctx.PostValue("name")
        message := ctx.PostValue("message")
        ctx.Writef("id: %d; page: %d; name: %s; message: %s", id, page, name, message)
    })
    app.Listen(":8080")
}
id: 1234; page: 1; name: kataras; message: this_is_great

(adsbygoogle = window.adsbygoogle || []).push({});

查询和发布表单参数

POST /post?id=a&id=b&id=c&name=john&name=doe&name=kataras
Content-Type: application/x-www-form-urlencoded
func main() {
    app := iris.Default()
    app.Post("/post", func(ctx iris.Context) {
        ids := ctx.URLParamSlice("id")
        names, err := ctx.PostValues("name")
        if err != nil {
            ctx.StopWithError(iris.StatusBadRequest, err)
            return
        }
        ctx.Writef("ids: %v; names: %v", ids, names)
    })
    app.Listen(":8080")
}
id [a b c], names: [john doe kataras]

上传文件

单个文件
const maxSize = 8 * iris.MB
func main() {
    app := iris.Default()
    app.Post("/upload", func(ctx iris.Context) {
        // Set a lower memory limit for multipart forms (default is 32 MiB)
        ctx.SetMaxRequestBodySize(maxSize)
        // OR
        // app.Use(iris.LimitRequestBodySize(maxSize))
        // OR
        // OR iris.WithPostMaxMemory(maxSize)
        // single file
        file, fileHeader, err:= ctx.FormFile("file")
        if err != nil {
            ctx.StopWithError(iris.StatusBadRequest, err)
            return
        }
        // Upload the file to specific destination.
        dest := filepath.Join("./uploads", fileHeader.Filename)
        ctx.SaveFormFile(fileHeader, dest)
        ctx.Writef("File: %s uploaded!", fileHeader.Filename)
    })
    app.Listen(":8080")
}

如何:curl

curl -X POST http://localhost:8080/upload \
  -F "file=@/Users/kataras/test.zip" \
  -H "Content-Type: multipart/form-data"
多个文件

请参阅详细的示例代码

func main() {
    app := iris.Default()
    app.Post("/upload", func(ctx iris.Context) {
        files, n, err := ctx.UploadFormFiles("./uploads")
        if err != nil {
            ctx.StopWithStatus(iris.StatusInternalServerError)
            return
        }
        ctx.Writef("%d files of %d total size uploaded!", len(files), n))
    })
    app.Listen(":8080", iris.WithPostMaxMemory(8 * iris.MB))
}

如何:curl

curl -X POST http://localhost:8080/upload \
  -F "upload[]=@/Users/kataras/test1.zip" \
  -F "upload[]=@/Users/kataras/test2.zip" \
  -H "Content-Type: multipart/form-data"

对路线进行分组

func main() {
    app := iris.Default()
    // Simple group: v1
    v1 := app.Party("/v1")
    {
        v1.Post("/login", loginEndpoint)
        v1.Post("/submit", submitEndpoint)
        v1.Post("/read", readEndpoint)
    }
    // Simple group: v2
    v2 := app.Party("/v2")
    {
        v2.Post("/login", loginEndpoint)
        v2.Post("/submit", submitEndpoint)
        v2.Post("/read", readEndpoint)
    }
    app.Listen(":8080")
}

默认不带中间件的空白光圈

app := iris.New()

而不是

// Default with "debug" Logger Level.
// Localization enabled on "./locales" directory
// and HTML templates on "./views" or "./templates" directory.
// It runs with the AccessLog on "./access.log",
// Recovery and Request ID middleware already attached.
app := iris.Default()

使用中间件

package main
import (
    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/middleware/recover"
)
func main() {
    // Creates an iris application without any middleware by default
    app := iris.New()
    // Global middleware using `UseRouter`.
    //
    // Recovery middleware recovers from any panics and writes a 500 if there was one.
    app.UseRouter(recover.New())
    // Per route middleware, you can add as many as you desire.
    app.Get("/benchmark", MyBenchLogger(), benchEndpoint)
    // Authorization group
    // authorized := app.Party("/", AuthRequired())
    // exactly the same as:
    authorized := app.Party("/")
    // per group middleware! in this case we use the custom created
    // AuthRequired() middleware just in the "authorized" group.
    authorized.Use(AuthRequired())
    {
        authorized.Post("/login", loginEndpoint)
        authorized.Post("/submit", submitEndpoint)
        authorized.Post("/read", readEndpoint)
        // nested group
        testing := authorized.Party("testing")
        testing.Get("/analytics", analyticsEndpoint)
    }
    // Listen and serve on 0.0.0.0:8080
    app.Listen(":8080")
}

(adsbygoogle = window.adsbygoogle || []).push({});

应用程序文件记录器

func main() {
    app := iris.Default()
    // Logging to a file.
    // Colors are automatically disabled when writing to a file.
    f, _ := os.Create("iris.log")
    app.Logger().SetOutput(f)
    // Use the following code if you need to write the logs
    // to file and console at the same time.
    // app.Logger().AddOutput(os.Stdout)
    app.Get("/ping", func(ctx iris.Context) {
        ctx.WriteString("pong")
    })
   app.Listen(":8080")
}

控制日志输出着色

默认情况下,控制台上的日志输出应根据检测到的 TTY 进行着色。

自定义关卡标题,文本,颜色和样式。

导入和 :golog``pio

import (
    "github.com/kataras/golog"
    "github.com/kataras/pio"
    // [...]
)

获取要自定义的级别,例如:DebugLevel

level := golog.Levels[golog.DebugLevel]

您可以完全控制他的文字、标题和风格:

// The Name of the Level
// that named (lowercased) will be used
// to convert a string level on `SetLevel`
// to the correct Level type.
Name string
// AlternativeNames are the names that can be referred to this specific log level.
// i.e Name = "warn"
// AlternativeNames = []string{"warning"}, it's an optional field,
// therefore we keep Name as a simple string and created this new field.
AlternativeNames []string
// Tha Title is the prefix of the log level.
// See `ColorCode` and `Style` too.
// Both `ColorCode` and `Style` should be respected across writers.
Title string
// ColorCode a color for the `Title`.
ColorCode int
// Style one or more rich options for the `Title`.
Style []pio.RichOption

示例代码:

level := golog.Levels[golog.DebugLevel]
level.Name = "debug" // default
level.Title = "[DBUG]" // default
level.ColorCode = pio.Yellow // default

要更改输出格式:

app.Logger().SetFormat("json", "    ")

注册自定义格式化程序:

app.Logger().RegisterFormatter(new(myFormatter))

嘟。格式化程序界面如下所示:

// Formatter is responsible to print a log to the logger's writer.
type Formatter interface {
    // The name of the formatter.
    String() string
    // Set any options and return a clone,
    // generic. See `Logger.SetFormat`.
    Options(opts ...interface{}) Formatter
    // Writes the "log" to "dest" logger.
    Format(dest io.Writer, log *Log) bool
}

要更改每个级别的输出和格式:

app.Logger().SetLevelOutput("error", os.Stderr)
app.Logger().SetLevelFormat("json")

请求日志记录

我们在上面看到的应用程序记录器用于记录与应用程序相关的信息和错误。另一方面,我们在下面看到的访问记录器用于记录传入的HTTP请求和响应。

package main
import (
    "os"
    "github.com/kataras/iris/v12"
    "github.com/kataras/iris/v12/middleware/accesslog"
)
// Read the example and its comments carefully.
func makeAccessLog() *accesslog.AccessLog {
    // Initialize a new access log middleware.
    ac := accesslog.File("./access.log")
    // Remove this line to disable logging to console:
    ac.AddOutput(os.Stdout)
    // The default configuration:
    ac.Delim = '|'
    ac.TimeFormat = "2006-01-02 15:04:05"
    ac.Async = false
    ac.IP = true
    ac.BytesReceivedBody = true
    ac.BytesSentBody = true
    ac.BytesReceived = false
    ac.BytesSent = false
    ac.BodyMinify = true
    ac.RequestBody = true
    ac.ResponseBody = false
    ac.KeepMultiLineError = true
    ac.PanicLog = accesslog.LogHandler
    // Default line format if formatter is missing:
    // Time|Latency|Code|Method|Path|IP|Path Params Query Fields|Bytes Received|Bytes Sent|Request|Response|
    //
    // Set Custom Formatter:
    ac.SetFormatter(&accesslog.JSON{
        Indent:    "  ",
        HumanTime: true,
    })
    // ac.SetFormatter(&accesslog.CSV{})
    // ac.SetFormatter(&accesslog.Template{Text: "{{.Code}}"})
    return ac
}
func main() {
    ac := makeAccessLog()
    defer ac.Close() // Close the underline file.
    app := iris.New()
    // Register the middleware (UseRouter to catch http errors too).
    app.UseRouter(ac.Handler)
    app.Get("/", indexHandler)
    app.Listen(":8080")
}
func indexHandler(ctx iris.Context) {
    ctx.WriteString("OK")
}

阅读更多示例:_examples/logging/request-logger

(adsbygoogle = window.adsbygoogle || []).push({});

模型绑定和验证

若要将请求正文绑定到类型中,请使用模型绑定。我们目前支持绑定、、、、和标准表单值(foo=bar&boo=baz)。JSON``JSONProtobuf``Protobuf``MsgPack``XML``YAML

ReadJSON(outPtr interface{}) error
ReadJSONProtobuf(ptr proto.Message, opts ...ProtoUnmarshalOptions) error
ReadProtobuf(ptr proto.Message) error
ReadMsgPack(ptr interface{}) error
ReadXML(outPtr interface{}) error
ReadYAML(outPtr interface{}) error
ReadForm(formObject interface{}) error
ReadQuery(ptr interface{}) error

使用 时,Iris 会尝试根据内容类型标头推断绑定程序。如果您确定要绑定的内容,则可以使用特定方法,例如 或和等ReadBody``ReadXXX``ReadJSON``ReadProtobuf

ReadBody(ptr interface{}) error

明智的是,Iris没有内置的数据验证功能。但是,它确实允许您附加一个验证器,该验证器将自动调用诸如 , …在这个例子中,我们将学习如何使用 go-playground/validator/v10 进行请求正文验证。ReadJSON``ReadXML

请注意,您需要在要绑定的所有字段上设置相应的绑定标记。例如,从 JSON 绑定时,设置 .json:"fieldname"

您还可以指定特定字段为必填字段。如果字段在绑定时用空值修饰,并且值为空,则会返回错误。binding:"required"

package main
import (
    "fmt"
    "github.com/kataras/iris/v12"
    "github.com/go-playground/validator/v10"
)
func main() {
    app := iris.New()
    app.Validator = validator.New()
    userRouter := app.Party("/user")
    {
        userRouter.Get("/validation-errors", resolveErrorsDocumentation)
        userRouter.Post("/", postUser)
    }
    app.Listen(":8080")
}
// User contains user information.
type User struct {
    FirstName      string     `json:"fname" validate:"required"`
    LastName       string     `json:"lname" validate:"required"`
    Age            uint8      `json:"age" validate:"gte=0,lte=130"`
    Email          string     `json:"email" validate:"required,email"`
    FavouriteColor string     `json:"favColor" validate:"hexcolor|rgb|rgba"`
    Addresses      []*Address `json:"addresses" validate:"required,dive,required"`
}
// Address houses a users address information.
type Address struct {
    Street string `json:"street" validate:"required"`
    City   string `json:"city" validate:"required"`
    Planet string `json:"planet" validate:"required"`
    Phone  string `json:"phone" validate:"required"`
}
type validationError struct {
    ActualTag string `json:"tag"`
    Namespace string `json:"namespace"`
    Kind      string `json:"kind"`
    Type      string `json:"type"`
    Value     string `json:"value"`
    Param     string `json:"param"`
}
func wrapValidationErrors(errs validator.ValidationErrors) []validationError {
    validationErrors := make([]validationError, 0, len(errs))
    for _, validationErr := range errs {
        validationErrors = append(validationErrors, validationError{
            ActualTag: validationErr.ActualTag(),
            Namespace: validationErr.Namespace(),
            Kind:      validationErr.Kind().String(),
            Type:      validationErr.Type().String(),
            Value:     fmt.Sprintf("%v", validationErr.Value()),
            Param:     validationErr.Param(),
        })
    }
    return validationErrors
}
func postUser(ctx iris.Context) {
    var user User
    err := ctx.ReadJSON(&user)
    if err != nil {
        // Handle the error, below you will find the right way to do that...
        if errs, ok := err.(validator.ValidationErrors); ok {
            // Wrap the errors with JSON format, the underline library returns the errors as interface.
            validationErrors := wrapValidationErrors(errs)
            // Fire an application/json+problem response and stop the handlers chain.
            ctx.StopWithProblem(iris.StatusBadRequest, iris.NewProblem().
                Title("Validation error").
                Detail("One or more fields failed to be validated").
                Type("/user/validation-errors").
                Key("errors", validationErrors))
            return
        }
        // It's probably an internal JSON error, let's dont give more info here.
        ctx.StopWithStatus(iris.StatusInternalServerError)
        return
    }
    ctx.JSON(iris.Map{"message": "OK"})
}
func resolveErrorsDocumentation(ctx iris.Context) {
    ctx.WriteString("A page that should document to web developers or users of the API on how to resolve the validation errors")
}

样品请求

{
    "fname": "",
    "lname": "",
    "age": 45,
    "email": "mail@example.com",
    "favColor": "#000",
    "addresses": [{
        "street": "Eavesdown Docks",
        "planet": "Persphone",
        "phone": "none",
        "city": "Unknown"
    }]
}

示例响应

{
    "title": "Validation error",
    "detail": "One or more fields failed to be validated",
    "type": "http://localhost:8080/user/validation-errors",
    "status": 400,
    "fields": [
    {
        "tag": "required",
        "namespace": "User.FirstName",
        "kind": "string",
        "type": "string",
        "value": "",
        "param": ""
    },
    {
        "tag": "required",
        "namespace": "User.LastName",
        "kind": "string",
        "type": "string",
        "value": "",
        "param": ""
    }
    ]
}

有关模型验证的更多信息,请访问:https://github.com/go-playground/validator/blob/master/_examples

绑定查询字符串

该方法仅绑定查询参数,而不绑定帖子数据,而是用于绑定帖子数据。ReadQuery``ReadForm

package main
import "github.com/kataras/iris/v12"
type Person struct {
    Name    string `url:"name,required"`
    Address string `url:"address"`
}
func main() {
    app := iris.Default()
    app.Any("/", index)
    app.Listen(":8080")
}
func index(ctx iris.Context) {
    var person Person
    if err := ctx.ReadQuery(&person); err!=nil {
        ctx.StopWithError(iris.StatusBadRequest, err)
        return
    }
    ctx.Application().Logger().Infof("Person: %#+v", person)
    ctx.WriteString("Success")
}

绑定任何

根据客户端发送数据的内容类型将请求正文绑定到“ptr”,例如 JSON、XML、YAML、MessagePack、Protobuf、Form 和 URL Query。

package main
import (
    "time"
    "github.com/kataras/iris/v12"
)
type Person struct {
        Name       string    `form:"name" json:"name" url:"name" msgpack:"name"` 
        Address    string    `form:"address" json:"address" url:"address" msgpack:"address"`
        Birthday   time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1" json:"birthday" url:"birthday" msgpack:"birthday"`
        CreateTime time.Time `form:"createTime" time_format:"unixNano" json:"create_time" url:"create_time" msgpack:"createTime"`
        UnixTime   time.Time `form:"unixTime" time_format:"unix" json:"unix_time" url:"unix_time" msgpack:"unixTime"`
}
func main() {
    app := iris.Default()
    app.Any("/", index)
    app.Listen(":8080")
}
func index(ctx iris.Context) {
    var person Person
    if err := ctx.ReadBody(&person); err!=nil {
        ctx.StopWithError(iris.StatusBadRequest, err)
        return
    }
    ctx.Application().Logger().Infof("Person: %#+v", person)
    ctx.WriteString("Success")
}

测试它:

$ curl -X GET "localhost:8085/testing?name=kataras&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033"

绑定网址路径参数

package main
import "github.com/kataras/iris/v12"
type myParams struct {
    Name string   `param:"name"`
    Age  int      `param:"age"`
    Tail []string `param:"tail"`
}
// All parameters are required, as we already know,
// the router will fire 404 if name or int or tail are missing.
func main() {
    app := iris.Default()
    app.Get("/{name}/{age:int}/{tail:path}", func(ctx iris.Context) {
        var p myParams
        if err := ctx.ReadParams(&p); err != nil {
            ctx.StopWithError(iris.StatusInternalServerError, err)
            return
        }
        ctx.Writef("myParams: %#v", p)
    })
    app.Listen(":8088")
}

请求

$ curl -v http://localhost:8080/kataras/27/iris/web/framewor

(adsbygoogle = window.adsbygoogle || []).push({});

绑定标头

package main
import "github.com/kataras/iris/v12"
type myHeaders struct {
    RequestID      string `header:"X-Request-Id,required"`
    Authentication string `header:"Authentication,required"`
}
func main() {
    app := iris.Default()
    r.GET("/", func(ctx iris.Context) {
        var hs myHeaders
        if err := ctx.ReadHeaders(&hs); err != nil {
            ctx.StopWithError(iris.StatusInternalServerError, err)
            return
        }
        ctx.JSON(hs)
    })
    app.Listen(":8080")
}

请求

curl -H "x-request-id:373713f0-6b4b-42ea-ab9f-e2e04bc38e73" -H "authentication: Bearer my-token" \
http://localhost:8080

响应

{
  "RequestID": "373713f0-6b4b-42ea-ab9f-e2e04bc38e73",
  "Authentication": "Bearer my-token"
}

“绑定 HTML ”复选框

package main
import "github.com/kataras/iris/v12"
func main() {
    app := iris.New()
    app.RegisterView(iris.HTML("./templates", ".html"))
    app.Get("/", showForm)
    app.Post("/", handleForm)
    app.Listen(":8080")
}
func showForm(ctx iris.Context) {
    if err := ctx.View("form.html"); err!=nil {
        ctx.HTML("<h3>%s</h3>", err.Error())
        return
    }
}
type formExample struct {
    Colors []string `form:"colors[]"` // or just "colors".
}
func handleForm(ctx iris.Context) {
    var form formExample
    err := ctx.ReadForm(&form)
    if err != nil {
        ctx.StopWithError(iris.StatusBadRequest, err)
        return
    }
    ctx.JSON(iris.Map{"Colors": form.Colors})
}

templates/form.html

<form action="/" method="POST">
    <p>Check one or more colors</p>
    <label for="red">Red</label>
    <!-- name can be "colors" too -->
    <input type="checkbox" name="colors[]" value="red" id="red">
    <label for="green">Green</label>
    <input type="checkbox" name="colors[]" value="green" id="green">
    <label for="blue">Blue</label>
    <input type="checkbox" name="colors[]" value="blue" id="blue">
    <input type="submit">
</form>

响应

{
  "Colors": [
    "red",
    "green",
    "blue"
  ]
}

JSON、JSONP、XML、Markdown、YAML 和 MsgPack 渲染

详细示例可在此处找到。

func main() {
    app := iris.New()
    // iris.Map is an alias of map[string]interface{}
    app.Get("/json", func(ctx iris.Context) {
        ctx.JSON(iris.Map{"message": "hello", "status": iris.StatusOK})
    })
    // Use Secure field to prevent json hijacking.
    // It prepends `"while(1),"` to the body when the data is array.
    app.Get("/json_secure", func(ctx iris.Context) {
        response := []string{"val1", "val2", "val3"}
        options := iris.JSON{Indent: "", Secure: true}
        ctx.JSON(response, options)
        // Will output: while(1);["val1","val2","val3"]
    })
    // Use ASCII field to generate ASCII-only JSON
    // with escaped non-ASCII characters.
    app.Get("/json_ascii", func(ctx iris.Context) {
        response := iris.Map{"lang": "GO-虹膜", "tag": "<br>"}
        options := iris.JSON{Indent: "    ", ASCII: true}
        ctx.JSON(response, options)
        /* Will output:
           {
               "lang": "GO-\u8679\u819c",
               "tag": "\u003cbr\u003e"
           }
        */
    })
    // Normally, JSON replaces special HTML characters with their unicode entities.
    // If you want to encode such characters literally,
    // you SHOULD set the UnescapeHTML field to true.
    app.Get("/json_raw", func(ctx iris.Context) {
        options := iris.JSON{UnescapeHTML: true}
        ctx.JSON(iris.Map{
            "html": "<b>Hello, world!</b>",
        }, options)
        // Will output: {"html":"<b>Hello, world!</b>"}
    })
    app.Get("/json_struct", func(ctx iris.Context) {
        // You also can use a struct.
        var msg struct {
            Name    string `json:"user"`
            Message string
            Number  int
        }
        msg.Name = "Mariah"
        msg.Message = "hello"
        msg.Number = 42
        // Note that msg.Name becomes "user" in the JSON.
        // Will output: {"user": "Mariah", "Message": "hello", "Number": 42}
        ctx.JSON(msg)
    })
    app.Get("/jsonp", func(ctx iris.Context) {
        ctx.JSONP(iris.Map{"hello": "jsonp"}, iris.JSONP{Callback: "callbackName"})
    })
    app.Get("/xml", func(ctx iris.Context) {
        ctx.XML(iris.Map{"message": "hello", "status": iris.StatusOK})
    })
    app.Get("/markdown", func(ctx iris.Context) {
        ctx.Markdown([]byte("# Hello Dynamic Markdown -- iris"))
    })
    app.Get("/yaml", func(ctx iris.Context) {
        ctx.YAML(iris.Map{"message": "hello", "status": iris.StatusOK})
    })
    app.Get("/msgpack", func(ctx iris.Context) {
        u := User{
            Firstname: "John",
            Lastname:  "Doe",
            City:      "Neither FBI knows!!!",
            Age:       25,
        }
        ctx.MsgPack(u)
    })
    // Render using jsoniter instead of the encoding/json:
    app.Listen(":8080", iris.WithOptimizations)
}
普罗托布夫

Iris 支持原生 protobuf with 和 protobuf to JSON 编码和解码。Protobuf

package main
import (
    "app/protos"
    "github.com/kataras/iris/v12"
)
func main() {
    app := iris.New()
    app.Get("/", send)
    app.Get("/json", sendAsJSON)
    app.Post("/read", read)
    app.Post("/read_json", readFromJSON)
    app.Listen(":8080")
}
func send(ctx iris.Context) {
    response := &protos.HelloReply{Message: "Hello, World!"}
    ctx.Protobuf(response)
}
func sendAsJSON(ctx iris.Context) {
    response := &protos.HelloReply{Message: "Hello, World!"}
    options := iris.JSON{
        Proto: iris.ProtoMarshalOptions{
            AllowPartial: true,
            Multiline:    true,
            Indent:       "    ",
        },
    }
    ctx.JSON(response, options)
}
func read(ctx iris.Context) {
    var request protos.HelloRequest
    err := ctx.ReadProtobuf(&request)
    if err != nil {
        ctx.StopWithError(iris.StatusBadRequest, err)
        return
    }
    ctx.Writef("HelloRequest.Name = %s", request.Name)
}
func readFromJSON(ctx iris.Context) {
    var request protos.HelloRequest
    err := ctx.ReadJSONProtobuf(&request)
    if err != nil {
        ctx.StopWithError(iris.StatusBadRequest, err)
        return
    }
    ctx.Writef("HelloRequest.Name = %s", request.Name)
}

提供静态文件

func main() {
    app := iris.New()
    app.Favicon("./resources/favicon.ico")
    app.HandleDir("/assets", iris.Dir("./assets"))
    app.Listen(":8080")
}

该方法接受第三个可选参数:HandleDir``DirOptions

type DirOptions struct {
    // Defaults to "/index.html", if request path is ending with **/*/$IndexName
    // then it redirects to **/*(/) which another handler is handling it,
    // that another handler, called index handler, is auto-registered by the framework
    // if end developer does not managed to handle it by hand.
    IndexName string
    // PushTargets filenames (map's value) to
    // be served without additional client's requests (HTTP/2 Push)
    // when a specific request path (map's key WITHOUT prefix)
    // is requested and it's not a directory (it's an `IndexFile`).
    //
    // Example:
    //     "/": {
    //         "favicon.ico",
    //         "js/main.js",
    //         "css/main.css",
    //     }
    PushTargets map[string][]string
    // PushTargetsRegexp like `PushTargets` but accepts regexp which
    // is compared against all files under a directory (recursively).
    // The `IndexName` should be set.
    //
    // Example:
    // "/": regexp.MustCompile("((.*).js|(.*).css|(.*).ico)$")
    // See `iris.MatchCommonAssets` too.
    PushTargetsRegexp map[string]*regexp.Regexp
    // Cache to enable in-memory cache and pre-compress files.
    Cache DirCacheOptions
    // When files should served under compression.
    Compress bool
    // List the files inside the current requested directory if `IndexName` not found.
    ShowList bool
    // If `ShowList` is true then this function will be used instead
    // of the default one to show the list of files of a current requested directory(dir).
    // See `DirListRich` package-level function too.
    DirList DirListFunc
    // Files downloaded and saved locally.
    Attachments Attachments
    // Optional validator that loops through each requested resource.
    AssetValidator func(ctx *context.Context, name string) bool
}

详细了解文件服务器

(adsbygoogle = window.adsbygoogle || []).push({});

从上下文中提供数据

SendFile(filename string, destinationName string) error
SendFileWithRate(src, destName string, limit float64, burst int) error


Go 框架 iris 文档(二):https://developer.aliyun.com/article/1396603

目录
相关文章
|
2月前
|
中间件 Go 数据库
Go开发者必读:Gin框架的实战技巧与最佳实践
在当今快速发展的互联网时代,Web开发的需求日益增长。Go语言以其简洁、高效、并发性强的特点,成为了开发者们的首选。而在Go语言的众多Web框架中,Gin无疑是其中的佼佼者。本文将深入探讨Gin框架的特性、优势以及如何利用Gin构建高性能的Web应用。
|
25天前
|
JSON 缓存 物联网
推荐一款go语言的开源物联网框架-opengw
推荐一款go语言的开源物联网框架-opengw
34 4
|
1月前
|
开发框架 JSON Go
Go语言Web开发基础与框架探索
【2月更文挑战第21天】本文将带领读者深入了解Go语言在Web开发领域的基础知识和常用框架。通过介绍Go语言的Web开发特点、核心库的使用,以及流行框架如Gin、Echo等的基本用法和优势,帮助读者快速上手Go语言Web开发,提升开发效率。
|
1月前
|
关系型数据库 MySQL 数据库连接
实战演练:使用Go语言和ORM框架与数据库进行交互
【2月更文挑战第13天】本文将通过一个实战演练,展示如何使用Go语言和ORM(对象关系映射)框架与数据库进行交互。我们将选择一个流行的ORM框架,如GORM,来完成这个任务。通过实际编码,我们将演示如何连接数据库、执行CRUD操作、处理错误和异常,并展示ORM框架如何简化数据库操作过程。
|
1月前
|
SQL 关系型数据库 MySQL
Go语言中的ORM框架介绍
【2月更文挑战第13天】本文将介绍ORM(对象关系映射)框架在Go语言中的应用。ORM框架能够简化数据库操作,将数据库表映射为Go结构体,并提供了一系列方法来执行CRUD(创建、读取、更新、删除)操作。我们将探讨几个流行的Go语言ORM框架,包括GORM、SQLBoiler和Squirrel,并比较它们的特性和用法。
|
2月前
|
XML JSON Java
RPC框架之Thrift—实现Go和Java远程过程调用
RPC框架之Thrift—实现Go和Java远程过程调用
48 1
|
3月前
|
关系型数据库 MySQL Go
go语言使用Gin框架链接数据库
go语言使用Gin框架链接数据库
41 0
|
3天前
|
人工智能 Go 调度
掌握Go并发:Go语言并发编程深度解析
掌握Go并发:Go语言并发编程深度解析
|
6天前
|
数据采集 存储 Go
使用Go语言和chromedp库下载Instagram图片:简易指南
Go语言爬虫示例使用chromedp库下载Instagram图片,关键步骤包括设置代理IP、创建带代理的浏览器上下文及执行任务,如导航至用户页面、截图并存储图片。代码中新增`analyzeAndStoreImage`函数对图片进行分析和分类后存储。注意Instagram的反爬策略可能需要代码适时调整。
使用Go语言和chromedp库下载Instagram图片:简易指南