gorountine demo
package controllers
import (
"fmt"
"github.com/astaxie/beego"
"time"
)
type GoDemoController struct {
beego.Controller
}
// go协程打印顺序不一致(并行)
// @router /go/demo [*]
func (this *GoDemoController) Demo() {
for i := 0; i < 10; i++ { // 启动10个任务
go cal(i)
}
time.Sleep(2 * time.Second)
this.Ctx.WriteString("demos")
}
func cal(i int) {
fmt.Printf("i= %d\n", i)
}
/**
channel demo
*/
// 打印顺序不一致(并行)
// @router /go/channel/demo [*]
func (this *GoDemoController) ChannelDemo() {
Channel := make(chan bool, 10) // 带缓冲
for i := 0; i < 10; i++ {
// 为什么go访问? 如果是无缓冲的channel,在一个goroutine中实现发送和接收会发生死锁
go cal1(i, Channel)
}
for j := 0; j < 10; j++ {
<-Channel
}
close(Channel)
time.Sleep(2 * time.Second)
this.Ctx.WriteString("demos")
}
func cal1(i int, Channel chan bool) {
fmt.Printf("i= %d\n", i)
time.Sleep(2 * time.Second)
Channel <- true
}
/*
select demo
*/
// 写for打印no message
// @router /go/select/demo [*]
func (this *GoDemoController) SelectDemo() {
ChannelOne := make(chan int, 20)
ChannelTwo := make(chan string, 20)
go cal2(ChannelOne)
ChannelTwo <- "a"
ChannelTwo <- "b"
go func() {
//for {
select {
case a := <-ChannelOne:
fmt.Println("get one = ", a)
case b := <-ChannelTwo:
fmt.Println("get two = ", b)
default:
fmt.Println("no message")
}
//}
}()
this.Ctx.WriteString("select demo")
}
func cal2(oneChannel chan int) {
for i := 0; i < 10; i++ {
oneChannel <- i
fmt.Println("set one = ", i)
}
}
/**
模拟任务池
*/
// @router /go/task/demo [*]
func (this *GoDemoController) TaskDemo() {
// 接收任务
taskChannel := make(chan int, 20)
// 处理任务
resChannel := make(chan int, 20)
// 关闭任务
closeChannel := make(chan bool, 5)
go func() {
for i := 0; i < 10; i++ {// 启动10个任务
taskChannel <- i
}
close(taskChannel)
}()
// 处理任务
for i := 0; i < 5; i++ {
go Task(taskChannel, resChannel, closeChannel)
fmt.Println("处理任务", i)
}
// 当接收5个值后,说明5个任务都执行完成
go func() {
for i := 0; i < 5; i++ {
<-closeChannel // 从closeChannel获取值 , 没有值就会阻塞在这里
}
close(resChannel)
close(closeChannel)
}()
// for循环reschannel时,当channel关闭以后会退出循环
for i := range resChannel {
fmt.Println("res : ", i)
}
this.Ctx.WriteString("模拟任务池")
}
func Task(taskChannel chan int, resChannel chan int, closeChannel chan bool) {
for t := range taskChannel {
// 从task中拿出值 写入res中
resChannel <- t
}
// 写入状态到close
closeChannel <- true
}
原代码
// 获取评论列表
// @router /comment/ormlist [*]
func (this *CommentController) ORMList() {
// 获取剧集数
episodesId, _ := this.GetInt("episodesId")
// 获取页码
limit, _ := this.GetInt("limit")
offset, _ := this.GetInt("offset")
if episodesId == 0 {
this.Data["json"] = ReturnError(4001, "请选定剧集")
this.ServeJSON()
}
if limit == 0 {
limit = 12
}
num, comments, err := models.GetCommentList(episodesId, offset, limit)
if err != nil {
this.Data["json"] = ReturnError(4004, "没有相关内容")
this.ServeJSON()
}
var data []CommentInfo
var commentInfo CommentInfo
for _, v := range comments {
commentInfo.Id = v.Id
commentInfo.Content = v.Content
commentInfo.AddTime = v.AddTime
commentInfo.AddTimeTitle = DateFormat(v.AddTime)
commentInfo.UserId = v.UserId
commentInfo.Stamp = v.Stamp
commentInfo.PraiseCount = v.PraiseCount
fmt.Println(v.UserId)
// 获取用户信息
commentInfo.UserInfo, _ = models.RedisGetUserInfo(v.UserId)
data = append(data, commentInfo)
}
this.Data["json"] = ReturnSuccess(0, "success", data, num)
this.ServeJSON()
}
goroutine修改后
// 获取评论列表
// goroutine改造获取用户信息: 达到同时获取
// @router /comment/list [*]
func (this *CommentController) List() {
// 获取剧集数
episodesId, _ := this.GetInt("episodesId")
// 获取页码
limit, _ := this.GetInt("limit")
offset, _ := this.GetInt("offset")
if episodesId == 0 {
this.Data["json"] = ReturnError(4001, "请选定剧集")
this.ServeJSON()
}
if limit == 0 {
limit = 12
}
num, comments, err := models.GetCommentList(episodesId, offset, limit)
if err != nil {
this.Data["json"] = ReturnError(4004, "没有相关内容")
this.ServeJSON()
}
var data []CommentInfo
var commentInfo CommentInfo
// goroutine 改造
//获取uid Channel
uidChannel := make(chan int, 12) // 总共查询12条
closeChannel := make(chan bool, 5)
//结果channel
resChannel := make(chan models.UserInfo, 12)// 总共查询12条
// 把获取的uid放进channel中
go func() {
for _, v := range comments {
uidChannel <- v.UserId
}
close(uidChannel)
}()
// 处理uidChannel中的信息
for i := 0; i < 5; i++ { // 启动5个任务
go chanGetUserInfo(uidChannel, resChannel, closeChannel)
}
// 判断是否执行完成
go func() {
for i := 0; i < 5; i++ {
<-closeChannel
}
close(resChannel)
close(closeChannel)
}()
// reschannel 中获取数据
userInfoMap := make(map[int]models.UserInfo)
for r := range resChannel {
userInfoMap[r.Id] = r
}
for _, v := range comments {
commentInfo.Id = v.Id
commentInfo.Content = v.Content
commentInfo.AddTime = v.AddTime
commentInfo.AddTimeTitle = DateFormat(v.AddTime)
commentInfo.UserId = v.UserId
commentInfo.Stamp = v.Stamp
commentInfo.PraiseCount = v.PraiseCount
fmt.Println(v.UserId)
// 获取用户信息
commentInfo.UserInfo, _ = userInfoMap[v.UserId]
data = append(data, commentInfo)
}
this.Data["json"] = ReturnSuccess(0, "success", data, num)
this.ServeJSON()
}
func chanGetUserInfo(uidchannel chan int, resChannel chan models.UserInfo, closeChannel chan bool) {
for uid := range uidchannel {
res, err := models.RedisGetUserInfo(uid)
fmt.Println(res)
if err == nil {
resChannel <- res
}
}
closeChannel <- true
}