YoyoGo是一個使用Golang編寫的一個簡單、輕量、快速、基於依賴注入的微服務框架,目前依然在研發階段,歡迎Star以及一塊兒參與到框架的研發mysql
GitHub地址:https://github.com/yoyofx/yoyogogit
正在爲YoyoGo寫第一個博客應用,感謝Tassdar的加入,源代碼:https://github.com/yoyofxteam/YoyoBlog.git 請先Clone Star,項目會持續更新,~github
本文經過一套最爲基本的增刪改查,來實例應該如何在最短的時間內最輕鬆的使用YoyoGo建立出一個本身的Web應用golang
本文開發環境及依賴版本:web
如今開始咱們的造物之旅 o(////▽////)qsql
go爲咱們自帶了包管理 go get ,會從github幫咱們下載依賴,可是因爲總所周知的複雜緣由,咱們須要爲本身的本地配置一下代理加速:數據庫
go env -w GOPROXY=https://goproxy.cn,direct
打開GoLand ->new Project -->go moduleswindows
打開命令行,輸入:bash
go get github.com/yoyofx/yoyogo
成功的話會出現上圖的結果,若是超時請檢查本身是否成功的配置了加速,檢查方式爲:go env 查看GOPRIXY選項mvc
package main import ( YoyoGo "github.com/yoyofx/yoyogo/WebFramework" "github.com/yoyofx/yoyogo/WebFramework/Context" "github.com/yoyofx/yoyogo/WebFramework/Router" ) func main() { YoyoGo.CreateDefaultBuilder(func(router Router.IRouterBuilder) { router.GET("/info",func (ctx *Context.HttpContext) { ctx.JSON(200, Context.H{"msg": "Hello World"}) }) }).Build().Run() //默認端口號 :8080 }
啓動main函數,框架打印出進程ID和監聽端口號,Host啓動成功
咱們使用PostMan訪問一下咱們在上面代碼中建立的路由,Host返回Hello World,到這一步恭喜你完成了本身的第一個YoyoGo的Web應用的建立~( ̄▽ ̄~)(~ ̄▽ ̄)~
固然,這麼簡單的功能是不能知足咱們的,接下里咱們要完成一個單表的增刪改查來更加深刻的瞭解YoyoGo的使用:
一個正常的Web框架是確定須要一個配置文件來保存它的相關配置的,YoyoGo使用golang編寫,咱們基於雲原生的基調採用了YAML文件格式座位咱們的配置文件格式
首先咱們在根目錄下建立一個名爲:config_dev.yml的文件,文件名能夠隨意編寫,後綴標識當前環境是開發仍是生產,咱們在文件中輸入如下配置,接下來文件中的各個配置咱們都會在後面用到
yoyogo: application: name: Blogs #應用名 metadata: "develop" #當前env server: type: "fasthttp" #Server類型 address: ":8081" #監聽端口 path: "" max_request_size: 2096157 #最大請求體限制 mvc: template: "v1/{controller}/{action}" #路由規則 database: url: tcp(localhost:3306)/yoyoBlog?charset=utf8&parseTime=True #數據庫鏈接字符串 username: root password: 1234abcd
鏈接數據庫首先要獲取數據庫驅動
go get github.com/go-sql-driver/mysql
而後咱們要從上面的配置文件中讀取出配置文件的數據庫配置節點,進行鏈接,在YoyoGo中,讀取配置文件配置使用的接口是:Abstractions.IConfiguration,經過使用Iconfiguration的get方法讀取去配置文件的內容,語法爲「xxx.xxx.xxx , 咱們經過構造函數初始化一下這個接口的實例,至因而如何實現構造函數初始化的這個是YoyoGo的依賴注入實現的,到後面咱們會演示講解。
import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" "github.com/yoyofx/yoyogo/Abstractions" "strings" ) type BaseRepository struct { config Abstractions.IConfiguration } func NewBaseRepository(config Abstractions.IConfiguration) *BaseRepository { return &BaseRepository{config: config} } //初始化一個鏈接對象 func (baseRepository *BaseRepository) InitDBConn() *sql.DB { url := fmt.Sprint(baseRepository.config.Get("yoyogo.database.url")) 」 username := fmt.Sprint(baseRepository.config.Get("yoyogo.database.username")) password := fmt.Sprint(baseRepository.config.Get("yoyogo.database.password")) var sb = strings.Builder{} sb.WriteString(username) sb.WriteString(":") sb.WriteString(password) sb.WriteString("@") sb.WriteString(url) connStr := sb.String() fmt.Println(connStr) conn, err := sql.Open("mysql", connStr) if err != nil { fmt.Println(err) } return conn }
這部分代碼比較枯燥,惟一須要注意的依然是經過構造函數來進行BaseRepository的注入
import ( "fmt" "yoyoFxBlog/domain" "yoyoFxBlog/repository/repository_impl" ) type BlogService struct { baseRepository *repository_impl.BaseRepository } func NewBlogService(baseRepository *repository_impl.BaseRepository) *BlogService { return &BlogService{baseRepository: baseRepository} } func (service *BlogService) AddLog(blog domain.Blog) domain.Blog { conn := service.baseRepository.InitDBConn() defer conn.Close() stmt, err := conn.Prepare("INSERT INTO `blog` SET title=?,introduction=?,content=?") fmt.Println(err) res, err := stmt.Exec(blog.Title, blog.Introduction, blog.Content) fmt.Println(err) id, err := res.LastInsertId() blog.Id = int(id) return blog } func (service *BlogService) QueryBlogList(pageIndex int, pageSize int) domain.Page { conn := service.baseRepository.InitDBConn() defer conn.Close() res := domain.Page{} rows, err := conn.Query("SELECT COUNT(0) as count FROM `blog` ") if err != nil { } for rows.Next() { var count int err = rows.Scan(&count) res.TotalCount = count } start := (pageIndex - 1) * pageSize sql := fmt.Sprintf("SELECT *FROM `blog` ORDER BY creation_date LIMIT %d,%d", start, pageSize) rows, err = conn.Query(sql) if err != nil { fmt.Println(err) } blogList := make([]domain.Blog, 0) for rows.Next() { element := domain.Blog{} err := rows.Scan(&element.Id, &element.Title, &element.Introduction, &element.Content, &element.ViewCount, &element.Author, &element.CreationDate) if err != nil { continue } blogList = append(blogList, element) } res.Data = blogList return res }
首先咱們建立一個控制器和幾個接口,建立控制器要注意如下幾點:
全部控制器必須和 Mvc.ApiController的指針進行組合
爲了從請求中抓取參數,咱們使用到了go的tag特性,獲取參數的格式爲 param:"arg"
注意參數名要用雙引號包裹,切用於進行參數綁定的結構體必須和 *Mvc.Requst組合
接口中用於進行自動綁定的結構體必須是指針類型
經過控制器的名稱前綴來實現HTTP請求類型的限制,例如 GETXXX即爲只能使用Get請求
import ( "github.com/yoyofx/yoyogo/WebFramework/ActionResult" "github.com/yoyofx/yoyogo/WebFramework/Mvc" "yoyoFxBlog/domain" "yoyoFxBlog/service" ) type BlogController struct { *Mvc.ApiController blogService *service.BlogService } func NewBlogController(blogService *service.BlogService) *BlogController { return &BlogController{blogService: blogService} } //聲明用於從請求中自動綁定參數的結構體 type BlogRequest struct { *Mvc.RequestBody //必須添加標識能夠自動綁定 Id int `param:"id"` Title string `param:"title"` //標題 Introduction string `param:"introduction"` //簡介 Content string `param:"content"` //內容 ViewCount int `param:"viewCount"` //瀏覽次數 } type PageRequest struct { *Mvc.RequestBody PageIndex int `param:"pageIndex"` PageSize int `param:"pageSize"` } ///這裏注意參數必須是指針類型 func (controller *BlogController) AddBlog(blog *BlogRequest) ActionResult.IActionResult { data := controller.blogService.AddLog(domain.Blog{Id: blog.Id, Title: blog.Title, Introduction: blog.Introduction, Content: blog.Content, ViewCount: blog.ViewCount}) return ActionResult.Json{Data: data} } //使用GET開頭限制這個接口只能使用GET請求方式 func (controller *BlogController) GetBlogList(PageRequest *PageRequest) ActionResult.IActionResult { data := controller.blogService.QueryBlogList(PageRequest.PageIndex, PageRequest.PageSize) return ActionResult.Json{Data: data} } func (controller *BlogController) BlogList(PageRequest *PageRequest) ActionResult.IActionResult { data := controller.blogService.QueryBlogList(PageRequest.PageIndex, PageRequest.PageSize) return ActionResult.Json{Data: data} }
這裏有我們上文中講到的,自定義Host啓動依賴注入 ,咱們在這一步咱們初始化了配置文件,以及控制器和經過調用咱們前幾步定義的構造函數來實現依賴的注入
import ( "github.com/yoyofx/yoyogo/Abstractions" "github.com/yoyofx/yoyogo/DependencyInjection" YoyoGo "github.com/yoyofx/yoyogo/WebFramework" "github.com/yoyofx/yoyogo/WebFramework/Mvc" "yoyoFxBlog/controller" "yoyoFxBlog/repository/repository_impl" "yoyoFxBlog/service" ) func main() { webHost := CreateYoyoBlogBuilder().Build() webHost.Run() } func CreateYoyoBlogBuilder() *Abstractions.HostBuilder { //讀取配置文件 configuration := Abstractions.NewConfigurationBuilder().AddYamlFile("config").Build() return YoyoGo.NewWebHostBuilder(). UseConfiguration(configuration). Configure(func(app *YoyoGo.WebApplicationBuilder) { //配置咱們上一步寫好的Controller app.UseMvc(func(builder *Mvc.ControllerBuilder) { builder.AddController(controller.NewBlogController) }) }). //配置咱們以前幾步中定義好的構造函數來進行注入 ConfigureServices(func(serviceCollection *DependencyInjection.ServiceCollection) { serviceCollection.AddTransient(repository_impl.NewBaseRepository) serviceCollection.AddTransient(service.NewBlogService) }) }
關於IOC生命週期,咱們暫時提供了單例和瞬時兩種方式使用方法爲:
func ConfigBusiness(serviceCollection *DependencyInjection.ServiceCollection) { //瞬時 //直接注入一個容器 serviceCollection.AddTransient(repository_impl.NewBaseRepository) //爲注入的容器起一個名字,相似於Spring中爲 Bean命名 serviceCollection.AddTransientByName("NewBaseRepository",repository_impl.NewBaseRepository) //用接口的形式進行注入,用於一個接口多種實現的狀況 serviceCollection.AddTransientByImplements(repository_impl.NewBaseRepository, new(repository.BaseRepository)) //單例 serviceCollection.AddSingleton(repository_impl.NewBaseRepository) serviceCollection.AddSingletonByName("NewBaseRepository",repository_impl.NewBaseRepository) serviceCollection.AddTransientByImplements(repository_impl.NewBaseRepository, new(repository.BaseRepository)) }
啓動項目,訪問咱們剛纔定義的接口,若是你能看到下圖結果,恭喜你,你已經陳工掌握了YoyoGo的基本入門使用!(o゜▽゜)o☆[BINGO!]