YoyoGo使用指南
YoyoGo是一个使用Golang编写的一个简单、轻量、快速、基于依赖注入的微服务框架,目前依然在研发阶段,欢迎Star以及一起参与到框架的研发
GitHub地址:https://github.com/yoyofx/yoyogo
例子源代码:https://github.com/yoyofxteam/YoyoBlog.git 请先下载源码,在查看指南体验更加~
本文通过一套最为基本的增删改查,来实例应该如何在最短的时间内最轻松的使用YoyoGo创建出一个自己的Web应用
本文开发环境及依赖版本:
OS: Windows10 企业版
GoLang SDK: go1.15.5 windows/amd64
IDE: GoLand 2020
YoyoGo: v1.5.8
MySQL: 5.7
MySQL_Deiver: v1.5.0
现在开始我们的造物之旅 o(*////▽////*)q
一、安装YoyoGo
go为我们自带了包管理 go get ,会从github帮我们下载依赖,但是由于总所周知的复杂原因,我们需要为自己的本地配置一下加速
go env -w GOPROXY=https://goproxy.cn,direct
打开GoLand ->new Project -->go modules

打开命令行,输入:
go get github.com/yoyofx/yoyogo

成功的话会出现上图的结果,如果超时请检查自己是否成功的配置了加速,检查方式为:go env 查看GOPRIXY选项

二、启动Host,完成Hello World
创建main主函数在函数中输入以下golang代码
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 :</span>=<span style="color: #000000;"> service.baseRepository.InitDBConn()
defer conn.Close()
stmt, err :</span>= conn.Prepare(<span style="color: #800000;">"</span><span style="color: #800000;">INSERT INTO `blog` SET title=?,introduction=?,content=?</span><span style="color: #800000;">"</span><span style="color: #000000;">)
fmt.Println(err)
res, err :</span>=<span style="color: #000000;"> stmt.Exec(blog.Title, blog.Introduction, blog.Content)
fmt.Println(err)
id, err :</span>=<span style="color: #000000;"> res.LastInsertId()
blog.Id </span>= <span style="color: #0000ff;">int</span><span style="color: #000000;">(id)
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> 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 FROMblog")
if err != nil {}
</span><span style="color: #0000ff;">for</span><span style="color: #000000;"> rows.Next() {
</span><span style="color: #0000ff;">var</span> count <span style="color: #0000ff;">int</span><span style="color: #000000;">
err </span>= rows.Scan(&<span style="color: #000000;">count)
res.TotalCount </span>=<span style="color: #000000;"> count
}
start :</span>= (pageIndex - <span style="color: #800080;">1</span>) *<span style="color: #000000;"> pageSize
sql :</span>= fmt.Sprintf(<span style="color: #800000;">"</span><span style="color: #800000;">SELECT *FROM `blog` ORDER BY creation_date LIMIT %d,%d</span><span style="color: #800000;">"</span><span style="color: #000000;">, start, pageSize)
rows, err </span>=<span style="color: #000000;"> conn.Query(sql)
</span><span style="color: #0000ff;">if</span> err !=<span style="color: #000000;"> nil {
fmt.Println(err)
}
blogList :</span>= make([]domain.Blog, <span style="color: #800080;">0</span><span style="color: #000000;">)
</span><span style="color: #0000ff;">for</span><span style="color: #000000;"> rows.Next() {
element :</span>=<span style="color: #000000;"> domain.Blog{}
err :</span>= rows.Scan(&element.Id, &element.Title, &element.Introduction, &element.Content, &element.ViewCount, &element.Author, &<span style="color: #000000;">element.CreationDate)
</span><span style="color: #0000ff;">if</span> err !=<span style="color: #000000;"> nil {
</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">
}
blogList </span>=<span style="color: #000000;"> append(blogList, element) }
res.Data </span>=<span style="color: #000000;"> blogList
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> res
}
六、创建控制器
首先我们创建一个控制器和几个接口,创建控制器要注意以下几点:
1.所有控制器必须和 Mvc.ApiController的指针进行组合
2.为了从请求中抓取参数,我们使用到了go的tag特性,获取参数的格式为 `param:"arg"` 注意参数名要用双引号包裹,切用于进行参数绑定的结构体必须和 *Mvc.Requst组合
3.接口中用于进行自动绑定的结构体必须是指针类型
4.通过控制器的名称前缀来实现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 intparam:<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span><span style="color: #000000;">
Title stringparam:<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span>//标题
Introduction stringparam:<span style="color: #800000;">"</span><span style="color: #800000;">introduction</span><span style="color: #800000;">"</span>//简介
Content stringparam:<span style="color: #800000;">"</span><span style="color: #800000;">content</span><span style="color: #800000;">"</span>//内容
ViewCount intparam:<span style="color: #800000;">"</span><span style="color: #800000;">viewCount</span><span style="color: #800000;">"</span>//浏览次数
} type PageRequest struct {
*Mvc.RequestBody
PageIndex intparam:<span style="color: #800000;">"</span><span style="color: #800000;">pageIndex</span><span style="color: #800000;">"</span><span style="color: #000000;">
PageSize intparam:<span style="color: #800000;">"</span><span style="color: #800000;">pageSize</span><span style="color: #800000;">"</span><span style="color: #000000;">} ///这里注意参数必须是指针类型
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!]

感谢一路看到这里的各位,对YoyoGo感兴趣的朋友欢迎在评论区留下宝贵的意见,欢迎帮助我们点一个星星~
YoyoGo使用指南的更多相关文章
- JavaScript权威指南 - 函数
函数本身就是一段JavaScript代码,定义一次但可能被调用任意次.如果函数挂载在一个对象上,作为对象的一个属性,通常这种函数被称作对象的方法.用于初始化一个新创建的对象的函数被称作构造函数. 相对 ...
- UE4新手之编程指南
虚幻引擎4为程序员提供了两套工具集,可共同使用来加速开发的工作流程. 新的游戏类.Slate和Canvas用户接口元素以及编辑器功能可以使用C++语言来编写,并且在使用Visual Studio 或 ...
- JavaScript权威指南 - 对象
JavaScript对象可以看作是属性的无序集合,每个属性就是一个键值对,可增可删. JavaScript中的所有事物都是对象:字符串.数字.数组.日期,等等. JavaScript对象除了可以保持自 ...
- JavaScript权威指南 - 数组
JavaScript数组是一种特殊类型的对象. JavaScript数组元素可以为任意类型,最大容纳232-1个元素. JavaScript数组是动态的,有新元素添加时,自动更新length属性. J ...
- const extern static 终极指南
const extern static 终极指南 不管是从事哪种语言的开发工作,const extern static 这三个关键字的用法和原理都是我们必须明白的.本文将对此做出非常详细的讲解. co ...
- Atitit.研发管理软件公司的软资产列表指南
Atitit.研发管理软件公司的软资产列表指南 1. Isv模型下的软资产1 2. 实现层面implet1 3. 规范spec层1 4. 法则定律等val层的总结2 1. Isv模型下的软资产 Sof ...
- HA 高可用软件系统保养指南
又过了一年 618,六月是公司一年一度的大促月,一般提前一个月各系统就会减少需求和功能的开发,转而更多去关注系统可用性.稳定性和管控性等方面的非功能需求.大促前的准备工作一般叫作「备战」,可以把线上运 ...
- 第六代智能英特尔® 酷睿™ 处理器图形 API 开发人员指南
欢迎查看第六代智能英特尔® 酷睿™ 处理器图形 API 开发人员指南,该处理器可为开发人员和最终用户提供领先的 CPU 和图形性能增强.各种新特性和功能以及显著提高的性能. 本指南旨在帮助软件开发人员 ...
- Visual Studio Code 配置指南
Visual Studio Code (简称 VS Code)是由微软研发的一款免费.开源的跨平台文本(代码)编辑器.在我看来它是「一款完美的编辑器」. 本文是有关 VS Code 的特性介绍与配置指 ...
随机推荐
- vim编辑器使用简介
使用格式 vim [option] /path/to/somefile ... option: -o水平分割 -O垂直分割 +打开后在最后一行 +Num打开后在地Num行,加号与Num之间不能有空格 ...
- CSS总结(一)
1 css常用的一些属性 color: 文字颜色(前景色) font-size: 文字大小 font-family: 字体,比如:微软雅黑, 黑体,宋体,仿宋体,"Times New Rom ...
- 【译】理解Rust中的闭包
原文标题:Understanding Closures in Rust 原文链接:https://medium.com/swlh/understanding-closures-in-rust-21f2 ...
- Java 中数组转换为 List
目录 1 - int 型数组转换为 List 2 - List 转换为 int 型数组 3 - String 型数组转换为 List 4 - List 转换为 String 型数组 版权声明 开发中经 ...
- ubuntu12.04管理文件系统工具
ubuntu12.04管理文件系统工具 以前可以自动管理系统盘和移动硬盘,刚重新安装了UBUNTU12.04LTS之后不行了,原来是这个工具: "PCMANFM" 群星_-_偏偏喜 ...
- 1、线性DP 213. 打家劫舍 II
https://leetcode-cn.com/problems/house-robber-ii/ //rob 0, not rob n-1 || not rob 0,not rob n-1 ==&g ...
- UNP第13章——守护进程
1. 守护进程的启动方法 (1)系统初始化脚本启动,在系统启动阶段,按照如/etc目录或/etc/rc开头的目录中的某些脚本启动,这些守护进程一开始就有超级用户权限.如inetd,cron,Web服务 ...
- Idea eclipse 快捷键Debug调试
运行下一行 F6 进入下一次计算 F5 运行到下一个断电 F7 恢复运行 F8
- Python_算法汇总
1. 约瑟夫环: # 约瑟夫环:共31个数,每隔9个删除一个,要求输出前15个号码 a=[x for x in range(1,31)] #生成编号 del_number = 8 #该删除的编号 fo ...
- 我要进大厂之大数据ZooKeeper知识点(1)
01 让我们一起学大数据 老刘又回来啦!在实验室师兄师姐都找完工作之后,在结束各种科研工作之后,老刘现在也要为找工作而努力了,要开始大数据各个知识点的复习总结了.老刘会分享出自己的知识点总结,一是希望 ...