Skip to content

Latest commit

 

History

History
1057 lines (823 loc) · 35.5 KB

README_ZH.md

File metadata and controls

1057 lines (823 loc) · 35.5 KB

Logo created by @santoshanand Iris

build statusBackers on Open CollectiveSponsors on Open Collectivereport cardgithub closed issuesreleaseview exampleschatCLA assistant

Sponsor

Iris是一个超快、简单并且高效的Go语言Web开发框架。

Iris功能很强大,使用又很简单,它将会是你下一个网站、API服务或者分布式应用基础框架的不二之选。

看看别人是如何评价Iris,同时欢迎各位成为Iris星探,或者关注Iris facebook主页

Iris vs .NET Core(C#) vs Node.js (Express)

上图是第三发机构发布的REST Web框架的基准测试

Comparison with other frameworks

更新于: 2017年9月29,星期五_

前言 ♥️

在发现Iris之前,我想你一定也看过其它Go Web开发框架。也许你已经摩拳擦掌并马上要使用了,但我会很遗憾的告诉你,将来你还是会使用Iris的。不仅仅因为Iris性能卓越和使用简单,更重要的是Iris独树一帜,他可以让你成为真正的极客界摇滚明星。

不管你是想开发微服务或者大型Web应用,Iris都能满足你的需求。Iris可能是你在网上能找到最好的Web后台开发软件之一了。

Iris现在已经到第8版了,但是我们从未停止开发。有很多非常棒的功能已经提上开发日程了,而且我们非常乐意加入很多有创意的想法。

如果你想用CDN加速,我推荐用KeyCDN,因为KeyCDN简单、速度快而且稳定。

我们用微软开发的Visual Studio Code来开发Golang应用。

如果你之前使用nodejs做开发,恭喜你,Iris使用基本和expressjs一样。

内容列表

安装

仅仅依赖Go语言

$ go get -u github.com/kataras/iris

Iris使用vendor 包依赖管理方式。vendor包管理的方式可以有效处理包依赖更新问题

入门

package main

import "github.com/kataras/iris"

func main() {
    app := iris.New()
    // 从"./views"目录加载HTML模板
    // 模板解析html后缀文件
    // 此方式是用`html/template`标准包(Iris的模板引擎)
    app.RegisterView(iris.HTML("./views", ".html"))

    // HTTP方法: GET
    // 路径:     http://localhost:8080
    app.Get("/", func(ctx iris.Context) {
        // {{.message}} 和 "Hello world!" 字串绑定
        ctx.ViewData("message", "Hello world!")
        // 映射HTML模板文件路径 ./views/hello.html
        ctx.View("hello.html")
    })

    // HTTP方法:    GET
    // 路径:  http://localhost:8080/user/42
    //
    // 想在路径中用正则吗?So easy!
    // 如下所示
    // app.Get("/user/{id:string regexp(^[0-9]+$)}")
    app.Get("/user/{id:long}", func(ctx iris.Context) {
        userID, _ := ctx.Params().GetInt64("id")
        ctx.Writef("User ID: %d", userID)
    })

    // 绑定端口并启动服务.
    app.Run(iris.Addr(":8080"))
}

想要了解更多关于路径参数配置,戳这里.

<!-- file: ./views/hello.html -->
<html>
<head>
    <title>Hello Page</title>
</head>
<body>
    <h1>{{.message}}</h1>
</body>
</html>
$ go run main.go
> 在这里监听服务: http://localhost:8080
> 应用已经启动按键 CTRL+C 停止服务

想要实现当代码改变后自动重启应用吗?那就装个rizla工具,启动go文件用 rizla main.go 来代替 go run main.go

Iris的一些开发约定可以看看这里_examples/structuring

MVC指南

package main

import (
    "github.com/kataras/iris"
    "github.com/kataras/iris/mvc"
)

func main() {
    app := iris.New()

    app.Controller("/helloworld", new(HelloWorldController))

    app.Run(iris.Addr("localhost:8080"))
}

type HelloWorldController struct {
    mvc.C

    // [ Your fields here ]
    // Request lifecycle data
    // Models
    // Database
    // Global properties
}

//
// GET: /helloworld

func (c *HelloWorldController) Get() string {
    return "This is my default action..."
}

//
// GET: /helloworld/{name:string}

func (c *HelloWorldController) GetBy(name string) string {
    return "Hello " + name
}

//
// GET: /helloworld/welcome

func (c *HelloWorldController) GetWelcome() (string, int) {
    return "This is the GetWelcome action func...", iris.StatusOK
}

//
// GET: /helloworld/welcome/{name:string}/{numTimes:int}

func (c *HelloWorldController) GetWelcomeBy(name string, numTimes int) {
    // Access to the low-level Context,
    // output arguments are optional of course so we don't have to use them here.
    c.Ctx.Writef("Hello %s, NumTimes is: %d", name, numTimes)
}

_examples/mvc 和 mvc/controller_test.go 两个简单的例子可以让你更好的了解 Iris MVC 的使用方式

每一个在controller中导出的Go方法名都和HTTP方法(Get, Post, Put, Delete...) 一一对应

在Web应用中一个HTTP访问的资源就是一个URL(统一资源定位符),比如http://localhost:8080/helloworld是由HTTP协议、Web服务网络位置(包括TCP端口):localhost:8080以及资源名称URI(统一资源标志符) /helloworld组成的。

上面例子第一个方法映射到HTTP GET方法,访问资源是"/helloworld",第三个方法映射到HTTP GET方法,访问资源是"/helloworld/welcome"

Controller在处理GetBy方法时可以识别路径‘name’参数,GetWelcomeBy方法可以识别路径‘name’和‘numTimes’参数,因为Controller在识别By关键字后可以动态灵活的处理路由;上面第四个方法指示使用 HTTP GET方法,而且只处理以"/helloworld/welcome"开头的资源位置路径,并且此路径还得包括两部分,第一部分类型没有限制,第二部分只能是数字类型,比如"http://localhost:8080/helloworld/welcome/golang/32719" 是合法的,其它的就会给客户端返回404 找不到的提示

MVC 快速指南 2

Iris对MVC的支持非常看看基准测试 ,Iris通过方法的返回值,可以给客户端返回任意类型的数据:

  • 如果返回的是 string 类型,就直接给客户端返回字符串
  • 如果第二个返回值是 string 类型,那么这个值就是ContentType(HTTP header)的值
  • 如果返回的是 int 类型,这个值就是HTTP状态码
  • 如果返回 error 值不是空,Iris 将会把这个值作为HTTP 400页面的返回值内容
  •  如果返回 (int, error) 类型,并且error不为空,那么Iris返回error的内容,同时把 int 值作为HTTP状态码
  • 如果返回 bool 类型,并且值是 false ,Iris直接返回404页面
  • 如果返回自定义 struct 、 interface{} 、 slice 及 map ,Iris 将按照JSON的方式返回,注意如果第二个返回值是 string,那么Iris就按照这个 string 值的ContentType处理了(不一定是'application/json')
  •  如果 mvc.Result 调用了 Dispatch 函数, 就会按照自己的逻辑重新处理

下面这些例子仅供参考,生产环境谨慎使用

package main

import (
    "github.com/kataras/iris"
    "github.com/kataras/iris/middleware/basicauth"
    "github.com/kataras/iris/mvc"
)

// Movie 是自定义数据结构
type Movie struct {
    Name   string `json:"name"`
    Year   int    `json:"year"`
    Genre  string `json:"genre"`
    Poster string `json:"poster"`
}

// movies 对象模拟数据源
var movies = []Movie{
    {
        Name:   "Casablanca",
        Year:   1942,
        Genre:  "Romance",
        Poster: "https://iris-go.com/images/examples/mvc-movies/1.jpg",
    },
    {
        Name:   "Gone with the Wind",
        Year:   1939,
        Genre:  "Romance",
        Poster: "https://iris-go.com/images/examples/mvc-movies/2.jpg",
    },
    {
        Name:   "Citizen Kane",
        Year:   1941,
        Genre:  "Mystery",
        Poster: "https://iris-go.com/images/examples/mvc-movies/3.jpg",
    },
    {
        Name:   "The Wizard of Oz",
        Year:   1939,
        Genre:  "Fantasy",
        Poster: "https://iris-go.com/images/examples/mvc-movies/4.jpg",
    },
}


var basicAuth = basicauth.New(basicauth.Config{
    Users: map[string]string{
        "admin": "password",
    },
})


func main() {
    app := iris.New()

    app.Use(basicAuth)

    app.Controller("/movies", new(MoviesController))

    app.Run(iris.Addr(":8080"))
}

// MoviesController 是 /movies controller.
type MoviesController struct {
    mvc.C
}

// 返回 movies列表
// 例子:
// curl -i http://localhost:8080/movies
func (c *MoviesController) Get() []Movie {
    return movies
}

// GetBy 返回一个 movie
// 例子:
// curl -i http://localhost:8080/movies/1
func (c *MoviesController) GetBy(id int) Movie {
    return movies[id]
}

// PutBy 更新一个 movie
// 例子:
// curl -i -X PUT -F "genre=Thriller" -F "poster=@/Users/kataras/Downloads/out.gif" http://localhost:8080/movies/1
func (c *MoviesController) PutBy(id int) Movie {
    // 获取一个 movie
    m := movies[id]

    // 获取一个poster文件
    file, info, err := c.Ctx.FormFile("poster")
    if err != nil {
        c.Ctx.StatusCode(iris.StatusInternalServerError)
        return Movie{}
    }
    file.Close()            // 我们不需要这个文件
    poster := info.Filename // 比如这就是上传的文件url
    genre := c.Ctx.FormValue("genre")

    // 更新poster
    m.Poster = poster
    m.Genre = genre
    movies[id] = m

    return m
}

// DeleteBy 删除一个 movie
// 例子:
// curl -i -X DELETE -u admin:password http://localhost:8080/movies/1
func (c *MoviesController) DeleteBy(id int) iris.Map {
    //从movies slice中删除索引
    deleted := movies[id].Name
    movies = append(movies[:id], movies[id+1:]...)
    // 返回删除movie的名称
    return iris.Map{"deleted": deleted}
}

MVC 快速指南 3

Iris是一个底层的Web开发框架,如果你喜欢按 目录结构 的约定方式开发,那么Iris框架对此毫无影响。

你可以根据自己的需求来创建目录结构,但是我建议你还是最好看看如下的目录结构例子:

目录结构例子

好了,直接上代码。

数据模型层

// file: datamodels/movie.go

package datamodels

// Movie是我们例子数据结构
// 此Movie可能会定义在类似"web/viewmodels/movie.go"的文件
// Movie的数据模型在应用中只有一个,这样使用就很简单了
type Movie struct {
    ID     int64  `json:"id"`
    Name   string `json:"name"`
    Year   int    `json:"year"`
    Genre  string `json:"genre"`
    Poster string `json:"poster"`
}

数据层 / 数据存储层

// file: datasource/movies.go

package datasource

import "github.com/kataras/iris/_examples/mvc/overview/datamodels"

// Movies是模拟的数据源
var Movies = map[int64]datamodels.Movie{
    1: {
        ID:     1,
        Name:   "Casablanca",
        Year:   1942,
        Genre:  "Romance",
        Poster: "https://iris-go.com/images/examples/mvc-movies/1.jpg",
    },
    2: {
        ID:     2,
        Name:   "Gone with the Wind",
        Year:   1939,
        Genre:  "Romance",
        Poster: "https://iris-go.com/images/examples/mvc-movies/2.jpg",
    },
    3: {
        ID:     3,
        Name:   "Citizen Kane",
        Year:   1941,
        Genre:  "Mystery",
        Poster: "https://iris-go.com/images/examples/mvc-movies/3.jpg",
    },
    4: {
        ID:     4,
        Name:   "The Wizard of Oz",
        Year:   1939,
        Genre:  "Fantasy",
        Poster: "https://iris-go.com/images/examples/mvc-movies/4.jpg",
    },
    5: {
        ID:     5,
        Name:   "North by Northwest",
        Year:   1959,
        Genre:  "Thriller",
        Poster: "https://iris-go.com/images/examples/mvc-movies/5.jpg",
    },
}

数据仓库

数据仓库层直接访问数据源

// file: repositories/movie_repository.go

package repositories

import (
    "errors"
    "sync"

    "github.com/kataras/iris/_examples/mvc/overview/datamodels"
)

// Query 是数据访问的集合入口
type Query func(datamodels.Movie) bool

// MovieRepository 中会有对movie实体的基本操作
type MovieRepository interface {
    Exec(query Query, action Query, limit int, mode int) (ok bool)

    Select(query Query) (movie datamodels.Movie, found bool)
    SelectMany(query Query, limit int) (results []datamodels.Movie)

    InsertOrUpdate(movie datamodels.Movie) (updatedMovie datamodels.Movie, err error)
    Delete(query Query, limit int) (deleted bool)
}

// NewMovieRepository 返回movie内存数据
func NewMovieRepository(source map[int64]datamodels.Movie) MovieRepository {
    return &movieMemoryRepository{source: source}
}

// movieMemoryRepository 就是 "MovieRepository",它管理movie的内存数据
type movieMemoryRepository struct {
    source map[int64]datamodels.Movie
    mu     sync.RWMutex
}

const (
    // 只读模式
    ReadOnlyMode = iota
    // 读写模式
    ReadWriteMode
)

func (r *movieMemoryRepository) Exec(query Query, action Query, actionLimit int, mode int) (ok bool) {
    loops := 0

    if mode == ReadOnlyMode {
        r.mu.RLock()
        defer r.mu.RUnlock()
    } else {
        r.mu.Lock()
        defer r.mu.Unlock()
    }

    for _, movie := range r.source {
        ok = query(movie)
        if ok {
            if action(movie) {
                loops++
                if actionLimit >= loops {
                    break // break
                }
            }
        }
    }

    return
}

// Select方法返回从模拟数据源找出的一个movie数据。
// 当找到时就返回true,并停止迭代
//
// Select 将会返回查询到的最新找到的movie数据,这样可以减少代码量
//
// 自从我第一次想到用这种简单的原型函数后,我就经常用它了,希望这也对你有用
func (r *movieMemoryRepository) Select(query Query) (movie datamodels.Movie, found bool) {
    found = r.Exec(query, func(m datamodels.Movie) bool {
        movie = m
        return true
    }, 1, ReadOnlyMode)

    // 如果没有找到就让datamodels.Movie为空
    // set an empty datamodels.Movie if not found at all.
    if !found {
        movie = datamodels.Movie{}
    }

    return
}

// 如果要查找很多值,用法基本一致,不过会返回datamodels.Movie slice。
// 如果limit<=0,将返回全部数据
func (r *movieMemoryRepository) SelectMany(query Query, limit int) (results []datamodels.Movie) {
    r.Exec(query, func(m datamodels.Movie) bool {
        results = append(results, m)
        return true
    }, limit, ReadOnlyMode)

    return
}

// 插入或更新数据
//
// 返回一个新的movie对象和error对象
func (r *movieMemoryRepository) InsertOrUpdate(movie datamodels.Movie) (datamodels.Movie, error) {
    id := movie.ID

    if id == 0 { // Create new action
        var lastID int64
        // 为了数据不重复,找到最大的ID。
        // 生产环境你可以用第三方库生成一个UUID字串
        r.mu.RLock()
        for _, item := range r.source {
            if item.ID > lastID {
                lastID = item.ID
            }
        }
        r.mu.RUnlock()

        id = lastID + 1
        movie.ID = id

        // map-specific thing
        r.mu.Lock()
        r.source[id] = movie
        r.mu.Unlock()

        return movie, nil
    }
    //通过movie.ID更新数据
    //这里举个例子看如果更新非空的poster和genre
    //其实我们可以直接更新对象r.source[id] = movie
    //用Select的话如下所示
    current, exists := r.Select(func(m datamodels.Movie) bool {
        return m.ID == id
    })

    if !exists { // ID不存在,返回error ID
        return datamodels.Movie{}, errors.New("failed to update a nonexistent movie")
    }

    // 或者直接对象操作替换
    // or comment these and r.source[id] = m for pure replace
    if movie.Poster != "" {
        current.Poster = movie.Poster
    }
    
    if movie.Genre != "" {
        current.Genre = movie.Genre
    }

    // 类map结构的处理
    r.mu.Lock()
    r.source[id] = current
    r.mu.Unlock()

    return movie, nil
}

func (r *movieMemoryRepository) Delete(query Query, limit int) bool {
    return r.Exec(query, func(m datamodels.Movie) bool {
        delete(r.source, m.ID)
        return true
    }, limit, ReadWriteMode)
}

服务层

服务层主要调用“数据仓库”和“数据模型”的方法(即使是数据模型很简单的应用)。这一层将包含主要的数据处理逻辑。

// file: services/movie_service.go

package services

import (
    "github.com/kataras/iris/_examples/mvc/overview/datamodels"
    "github.com/kataras/iris/_examples/mvc/overview/repositories"
)

// MovieService主要包括对movie的CRUID(增删改查)操作。
// MovieService主要调用movie 数据仓库的方法。
// 下面例子的数据源是更高级别的组件
// 这样可以用同样的逻辑可以返回不同的数据仓库
// MovieService是一个接口,任何实现的地方都能用,这样可以替换不同的业务逻辑用来测试
type MovieService interface {
    GetAll() []datamodels.Movie
    GetByID(id int64) (datamodels.Movie, bool)
    DeleteByID(id int64) bool
    UpdatePosterAndGenreByID(id int64, poster string, genre string) (datamodels.Movie, error)
}

// NewMovieService 返回一个 movie 服务.
func NewMovieService(repo repositories.MovieRepository) MovieService {
    return &movieService{
        repo: repo,
    }
}

type movieService struct {
    repo repositories.MovieRepository
}

// GetAll 返回所有 movies.
func (s *movieService) GetAll() []datamodels.Movie {
    return s.repo.SelectMany(func(_ datamodels.Movie) bool {
        return true
    }, -1)
}

// GetByID 是通过id找到movie.
func (s *movieService) GetByID(id int64) (datamodels.Movie, bool) {
    return s.repo.Select(func(m datamodels.Movie) bool {
        return m.ID == id
    })
}


// UpdatePosterAndGenreByID 更新一个 movie的 poster 和 genre.
func (s *movieService) UpdatePosterAndGenreByID(id int64, poster string, genre string) (datamodels.Movie, error) {
    // update the movie and return it.
    return s.repo.InsertOrUpdate(datamodels.Movie{
        ID:     id,
        Poster: poster,
        Genre:  genre,
    })
}

// DeleteByID 通过id删除一个movie
//
// 返回true表示成功,其它都是失败
func (s *movieService) DeleteByID(id int64) bool {
    return s.repo.Delete(func(m datamodels.Movie) bool {
        return m.ID == id
    }, 1)
}

视图模型

视图模型将处理结果返回给客户端

例子: Example:

import (
    "github.com/kataras/iris/_examples/mvc/overview/datamodels"

    "github.com/kataras/iris/context"
)

type Movie struct {
    datamodels.Movie
}

func (m Movie) IsValid() bool {
    /* 做一些检测,如果ID合法就返回true */
    return m.ID > 0
}

Iris允许在HTTP Response Dispatcher中使用任何自定义数据结构, 所以理论上来说,除非万不得已,下面的代码不建议使用

// Dispatch实现了`kataras/iris/mvc#Result`接口。在函数最后发送了一个`Movie`对象作为http response对象。
// 如果ID小于等于0就回返回404,或者就返回json数据。
//(这样就像控制器的方法默认返回自定义类型一样)
//
// 不要在这里写过多的代码,应用的主要逻辑不在这里
// 在方法返回之前可以做个简单验证处理等等;
//
// 这里只是一个小例子,想想这个优势在设计大型应用是很有作用的
//
// 这个方法是在`Movie`类型的控制器调用的。
// 例子在这里:`controllers/movie_controller.go#GetBy`。
func (m Movie) Dispatch(ctx context.Context) {
    if !m.IsValid() {
        ctx.NotFound()
        return
    }
    ctx.JSON(m, context.JSON{Indent: " "})
}

然而,我们仅仅用"datamodels"作为一个数据模型包,是因为Movie数据结构没有包含敏感数据,客户端可以访问到其所有字段,我们不需要再有额外的功能去做验证处理了

控制器

控制器处理Web请求,它是服务层和客户端之间的桥梁

// file: web/controllers/movie_controller.go

package controllers

import (
    "errors"

    "github.com/kataras/iris/_examples/mvc/overview/datamodels"
    "github.com/kataras/iris/_examples/mvc/overview/services"

    "github.com/kataras/iris"
    "github.com/kataras/iris/mvc"
)

// MovieController是/movies的控制器
type MovieController struct {
    mvc.C

    // MovieService是一个接口,主app对象会持有它
    Service services.MovieService
}

// 获取movies列表
// 例子:
// curl -i http://localhost:8080/movies
//
// 如果你有一些敏感的数据要处理的话,可以按照如下所示的方式:
// func (c *MovieController) Get() (results []viewmodels.Movie) {
//  data := c.Service.GetAll()
//
//  for _, movie := range data {
// 	  results = append(results, viewmodels.Movie{movie})
//  }
//  return
// }
//否则直接返回数据模型
func (c *MovieController) Get() (results []datamodels.Movie) {
    return c.Service.GetAll()
}

// GetBy返回一个movie对象
// 例子:
// curl -i http://localhost:8080/movies/1
func (c *MovieController) GetBy(id int64) (movie datamodels.Movie, found bool) {
    return c.Service.GetByID(id) // 404 没有找到
}

// PutBy更新一个movie.
// 例子:
// curl -i -X PUT -F "genre=Thriller" -F "poster=@/Users/kataras/Downloads/out.gif" http://localhost:8080/movies/1
func (c *MovieController) PutBy(id int64) (datamodels.Movie, error) {
    // 从请求中获取poster和genre
    file, info, err := c.Ctx.FormFile("poster")
    if err != nil {
        return datamodels.Movie{}, errors.New("failed due form file 'poster' missing")
    }
    // 关闭文件
    file.Close()

    //想象这就是一个上传文件的url
    poster := info.Filename
    genre := c.Ctx.FormValue("genre")

    return c.Service.UpdatePosterAndGenreByID(id, poster, genre)
}

// DeleteBy删除一个movie对象
// 例子:
// curl -i -X DELETE -u admin:password http://localhost:8080/movies/1
func (c *MovieController) DeleteBy(id int64) interface{} {
    wasDel := c.Service.DeleteByID(id)
    if wasDel {
        // 返回要删除的ID
        return iris.Map{"deleted": id}
    }
    //现在我们可以看到这里可以返回一个有2个返回值(map或int)的函数
    //我们并没有指定一个返回的类型
    return iris.StatusBadRequest
}
// file: web/controllers/hello_controller.go

package controllers

import (
    "errors"

    "github.com/kataras/iris/mvc"
)

// HelloController是控制器的例子
// 下面会处理GET: /hello and GET: /hello/{name}
type HelloController struct {
    mvc.C
}

var helloView = mvc.View{
    Name: "hello/index.html",
    Data: map[string]interface{}{
        "Title":     "Hello Page",
        "MyMessage": "Welcome to my awesome website",
    },
}

// Get会返回预定义绑定数据的视图
//
// `mvc.Result`是一个含有`Dispatch`方法的接口
// `mvc.Response` 和 `mvc.View` dispatchers 内置类型
// 你也可以通过实现`github.com/kataras/iris/mvc#Result`接口来自定义dispatchers
func (c *HelloController) Get() mvc.Result {
    return helloView
}

// 你可以定义一个标准通用的error
var errBadName = errors.New("bad name")

//你也可以将error包裹在mvc.Response中,这样就和mvc.Result类型兼容了
var badName = mvc.Response{Err: errBadName, Code: 400}

// GetBy 返回 "Hello {name}" response
// 例子:
// curl -i http://localhost:8080/hello/iris
// curl -i http://localhost:8080/hello/anything
func (c *HelloController) GetBy(name string) mvc.Result {
    if name != "iris" {
        return badName
        // 或者
        // GetBy(name string) (mvc.Result, error) {
        //  return nil, errBadName
        // }
    }

    // 返回 mvc.Response{Text: "Hello " + name} 或者:
    return mvc.View{
        Name: "hello/name.html",
        Data: name,
    }
}
// file: web/middleware/basicauth.go

package middleware

import "github.com/kataras/iris/middleware/basicauth"

// BasicAuth 中间件例
var BasicAuth = basicauth.New(basicauth.Config{
    Users: map[string]string{
        "admin": "password",
    },
})
<!-- file: web/views/hello/index.html -->
<html>

<head>
    <title>{{.Title}} - My App</title>
</head>

<body>
    <p>{{.MyMessage}}</p>
</body>

</html>
<!-- file: web/views/hello/name.html -->
<html>

<head>
    <title>{{.}}' Portfolio - My App</title>
</head>

<body>
    <h1>Hello {{.}}</h1>
</body>

</html>

_examples/view 可以找到更多关于layouts,tmpl,routing的例子

程序入口

程序入口可以将任何组件包含进来

// file: main.go

package main

import (
    "github.com/kataras/iris/_examples/mvc/overview/datasource"
    "github.com/kataras/iris/_examples/mvc/overview/repositories"
    "github.com/kataras/iris/_examples/mvc/overview/services"
    "github.com/kataras/iris/_examples/mvc/overview/web/controllers"
    "github.com/kataras/iris/_examples/mvc/overview/web/middleware"

    "github.com/kataras/iris"
)

func main() {
    app := iris.New()

    // 加载模板文件
    app.RegisterView(iris.HTML("./web/views", ".html"))

    // 注册控制器
    app.Controller("/hello", new(controllers.HelloController))

    // 创建movie 数据仓库,次仓库包含的是内存级的数据源
    repo := repositories.NewMovieRepository(datasource.Movies)
    // 创建movie服务, 然后将其与控制器绑定
    movieService := services.NewMovieService(repo)

    app.Controller("/movies", new(controllers.MovieController),
        // 将"movieService"绑定在 MovieController的Service接口
        movieService,
        // 为/movies请求添加basic authentication(admin:password)中间件
        middleware.BasicAuth)

    // 启动应用localhost:8080
    // http://localhost:8080/hello
    // http://localhost:8080/hello/iris
    // http://localhost:8080/movies
    // http://localhost:8080/movies/1
    app.Run(
        iris.Addr("localhost:8080"),
        iris.WithoutVersionChecker,
        iris.WithoutServerError(iris.ErrServerClosed),
        iris.WithOptimizations, // 可以启用快速json序列化等优化配置
    )
}

更多指南戳 _examples/#structuring

现在你已经准备好进入下一阶段,又向专家级gopher迈进一步了

恭喜你看到这里了,我们为你准备了更高水平的内容,向真正的专家级gopher进军吧😃

准备好咖啡,尽情享受吧!

作者

Iris的作者是@kataras, 你可以通过以下方式来了解作者:

作者

贡献者列表

你可以通过PayPal 或 BTC来捐赠这个项目,这样可以促进开发者们创造更棒、更优秀的Iris。

如何贡献代码

我们期待你能帮助我们翻译Iris文档

Iris需要你的帮助,帮助我们翻译READMEhttps://iris-go.com ,同时你也会得到奖励的。

你可以在这里kataras#796 看到详细的有关翻译的信息

Iris 用户体验反馈 | 2017年10月3号

请放心 Iris用户体验反馈就是一些简单的表单提交,2分钟就能搞定。

这些表单里有些问题是为了更好的了解你,了解你可以让我们更好的为你服务。

https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link

贡献者列表

非常感谢所有对Iris的贡献者,没有你们就没有Iris 贡献者

资助者

万分感谢所有的资助者🙏 成为资助者

赞助商

资助Iris,你将是Iris的赞助商,你的logo将会出现在下面的列表中,成为赞助商

开源许可证

Iris使用3-Clause BSD 许可证开源许可 。Iris绝对是100%开源的。 对这个许可有任何疑问请联系我们