Iris 這個在 go 語言上地表最快的網頁框架-iris的依賴注入

iris的依賴注入

本篇文章介紹一下其他語言也有的設計概念,就是依賴注入,以及在iris如何利用這種設計概念讓程式的組件職能分工,並且能每個組件專注在各自的邏輯開發。

iris的依賴注入

本篇介紹iris的依賴注入,首先先由什麼是依賴注入開始,讓大家對於這種設計概念有一些初步的概念,然後再帶到如何在iris利用依賴注入的方式來開發,所有先跟大家介紹依賴注入。

依賴注入

提到依賴注入就不能不提另一個概念就是控制反轉IoC,這個概念的起因是因為有個人想說為什麼都是類別決定需要什麼組件呢,為什麼不能反過來讓外部決定類別需要的組件呢,所以就成了今天要說明的主題依賴注入。
這時候讀者會好奇那怎麼由外部決定類別要相依的組件呢,簡單來說類別只要相依介面interface就好了,不要相依到實體,如此就可以由外部來決定這個類別要相依的實體是什麼,換一句話來說就是在外部來注入類別所依賴的組件,所以接下來開始介紹怎麼在iris中實作依賴注入的設計概念。

iris的依賴注入

iris的依賴注入文件中有詳細的說明如何在iris中用依賴注入的方式開發,不過其內容有點複雜,所以我們直接看iris官方依賴注入的範例,雖然個範例的程式碼很多,但是對於依賴注入的內容只有一些,所以接下來針對這些內容跟大家說明。
首先請大家看一下下列的例子

// file: web/routes/movie.go
package routes

import (
    "errors"

    "github.com/kataras/iris/v12/_examples/dependency-injection/overview/datamodels"
    "github.com/kataras/iris/v12/_examples/dependency-injection/overview/services"

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

// Movies returns list of the movies.
// Demo:
// curl -i http://localhost:8080/movies
func Movies(service services.MovieService) (results []datamodels.Movie) {
    return service.GetAll()
}

// MovieByID returns a movie.
// Demo:
// curl -i http://localhost:8080/movies/1
func MovieByID(service services.MovieService, id uint64) (movie datamodels.Movie, found bool) {
    return service.GetByID(id) // it will throw 404 if not found.
}

// UpdateMovieByID updates a movie.
// Demo:
// curl -i -X PUT -F "genre=Thriller" -F "poster=@/Users/kataras/Downloads/out.gif" http://localhost:8080/movies/1
func UpdateMovieByID(ctx iris.Context, service services.MovieService, id uint64) (datamodels.Movie, error) {
    // get the request data for poster and genre
    file, info, err := ctx.FormFile("poster")
    if err != nil {
        return datamodels.Movie{}, errors.New("failed due form file 'poster' missing")
    }
    // we don't need the file so close it now.
    file.Close()

    // imagine that is the url of the uploaded file...
    poster := info.Filename
    genre := ctx.FormValue("genre")

    return service.UpdatePosterAndGenreByID(id, poster, genre)
}

// DeleteMovieByID deletes a movie.
// Demo:
// curl -i -X DELETE -u admin:password http://localhost:8080/movies/1
func DeleteMovieByID(service services.MovieService, id uint64) interface{} {
    wasDel := service.DeleteByID(id)
    if wasDel {
        // return the deleted movie's ID
        return iris.Map{"deleted": id}
    }
    // right here we can see that a method function can return any of those two types(map or int),
    // we don't have to specify the return type to a specific type.
    return iris.StatusBadRequest
}

上面是需要傳入一個MovieService的handler而這個MovieService就是我們定義的interface所以我們這個handler直接相依這個interface而不在乎這interface的實作是什麼,所以接下來我們只要註冊實作這interface`的實體並注入即可,所以我們再看看下面例子來了解如何注入。

// file: main.go
package main

import (
    "github.com/kataras/iris/v12/_examples/dependency-injection/overview/datasource"
    "github.com/kataras/iris/v12/_examples/dependency-injection/overview/repositories"
    "github.com/kataras/iris/v12/_examples/dependency-injection/overview/services"
    "github.com/kataras/iris/v12/_examples/dependency-injection/overview/web/middleware"
    "github.com/kataras/iris/v12/_examples/dependency-injection/overview/web/routes"

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

func main() {
    app := iris.New()
    app.Logger().SetLevel("debug")

    // Load the template files.
    app.RegisterView(iris.HTML("./web/views", ".html"))

    // Create our movie repository with some (memory) data from the datasource.
    repo := repositories.NewMovieRepository(datasource.Movies)

    app.Party("/hello").ConfigureContainer(func(r *iris.APIContainer) {
        r.Get("/", routes.Hello)
        r.Get("/{name}", routes.HelloName)
    })

    app.Party("/movies").ConfigureContainer(func(r *iris.APIContainer) {
        // Create our movie service, we will bind it to the movie app's dependencies.
        movieService := services.NewMovieService(repo)
        r.RegisterDependency(movieService)

        // Add the basic authentication(admin:password) middleware
        // for the /movies based requests.
        r.Use(middleware.BasicAuth)

        r.Get("/", routes.Movies)
        r.Get("/{id:uint64}", routes.MovieByID)
        r.Put("/{id:uint64}", routes.UpdateMovieByID)
        r.Delete("/{id:uint64}", routes.DeleteMovieByID)
    })

    // http://localhost:8080/hello
    // http://localhost:8080/hello/iris
    // http://localhost:8080/movies ("admin": "password")
    // http://localhost:8080/movies/1
    app.Listen(
        // Start the web server at localhost:8080
        "localhost:8080",
        // enables faster json serialization and more:
        iris.WithOptimizations,
    )
}

相信大家都可以看到我們綁定handler之前會呼叫Party("/movies").ConfigureContainer(func(r *iris.APIContainer)這一段,並且呼叫r.RegisterDependency(movieService)來呼叫註冊service如此在綁定handler之後當handler被呼叫時會註冊該service給其使用了。
至於service以及repository的實作就不是本篇文章的重點,還請讀者們自行閱讀了。

結論

本篇介紹了依賴注入的內容以及如何在iris上使用依賴注入的方式進行開發,希望這篇文章可以幫助大家都程式開發。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *