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

目录
相关文章
|
18天前
|
开发框架 Go 计算机视觉
纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架
开发纯go插件的原因是因为目前 Go 生态系统中几乎所有现有的人脸检测解决方案都是纯粹绑定到一些 C/C++ 库,如 OpenCV 或 dlib,但通过 cgo 调用 C 程序会引入巨大的延迟,并在性能方面产生显著的权衡。此外,在许多情况下,在各种平台上安装 OpenCV 是很麻烦的。使用纯Go开发的插件不仅在开发时方便,在项目部署和项目维护也能省很多时间精力。
|
27天前
|
Go API 数据库
Go 语言中常用的 ORM 框架,如 GORM、XORM 和 BeeORM,分析了它们的特点、优势及不足,并从功能特性、性能表现、易用性和社区活跃度等方面进行了比较,旨在帮助开发者根据项目需求选择合适的 ORM 框架。
本文介绍了 Go 语言中常用的 ORM 框架,如 GORM、XORM 和 BeeORM,分析了它们的特点、优势及不足,并从功能特性、性能表现、易用性和社区活跃度等方面进行了比较,旨在帮助开发者根据项目需求选择合适的 ORM 框架。
74 4
|
27天前
|
中间件 Go API
Go语言中几种流行的Web框架,如Beego、Gin和Echo,分析了它们的特点、性能及适用场景,并讨论了如何根据项目需求、性能要求、团队经验和社区支持等因素选择最合适的框架
本文概述了Go语言中几种流行的Web框架,如Beego、Gin和Echo,分析了它们的特点、性能及适用场景,并讨论了如何根据项目需求、性能要求、团队经验和社区支持等因素选择最合适的框架。
70 1
|
3月前
|
JSON Go API
使用Go语言和Gin框架构建RESTful API:GET与POST请求示例
使用Go语言和Gin框架构建RESTful API:GET与POST请求示例
|
4月前
|
Cloud Native JavaScript API
一文读懂云原生 go-zero 微服务框架
一文读懂云原生 go-zero 微服务框架
|
3月前
|
消息中间件 NoSQL Go
PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
【9月更文挑战第7天】在从 PHP 的 ThinkPHP 框架迁移到 Go 的 Gin 框架时,涉及 Redis 延时消息队列的技术实践主要包括:理解延时消息队列概念,其能在特定时间处理消息,适用于定时任务等场景;在 ThinkPHP 中使用 Redis 实现延时队列;在 Gin 中结合 Go 的 Redis 客户端库实现类似功能;Go 具有更高性能和简洁性,适合处理大量消息。迁移过程中需考虑业务需求及系统稳定性。
|
4月前
|
SQL JavaScript Go
Go Web 服务框架实现详解
Go Web 服务框架实现详解
|
15天前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
26 7
|
15天前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
15天前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
92 71