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!]