PHP的朋友,写多了就会有一些疑惑PHP中,不同的请求之间是完全独立的PHP做不到, 我们也可以使用Redis之类的来达到共享内存使用package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func main() {
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
go func() {
var i int
for {
i ++
fmt.Println(i)
time.Sleep(time.Second)
}
}()
time.Sleep(time.Second * 5)
c.String(http.StatusOK, "pong")
})
router.Run(":8888")
}PHP的思想,预想可能会在控制台打印 1~5, 然后浏览器响应pong,请求结束goroutine不会被销毁,一直运行,如果大量的请求进来,那么就会导致内存泄漏.package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func main() {
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
go func() {
var i int
for {
select {
case <- c.Request.Context().Done():
return
default:
i ++
fmt.Println(i)
time.Sleep(time.Second)
}
}
}()
time.Sleep(time.Second * 5)
c.String(http.StatusOK, "pong")
})
router.Run(":8888")
}c.Request.Context().Done()状态即可handle还在处理任务,那么我们就不断打印goroutinePHP代码都是在goroutine handle的生命周期.PHP中实现用户注册之后异步发送邮件, 那么就需要借助其它办法实现(redis 队列)Go中可以独立开启一个goroutine去执行任何想要的操作,并且我们也可以在这个goroutine判断该什么时候结束.package main
import (
"context"
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
"net/http"
)
var ctx = context.Background()
func main() {
host := ""
port := 0
password := ""
client := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", host, port),
Password: password, // no password set
DB: 0, // use default DB
})
g := gin.Default()
g.GET("/ping", func(c *gin.Context) {
var msg string
// 1
msg = client.Get(ctx, "ping").String()
// 2
msg = client.Get(context.Background(), "ping").String()
// 3
msg = client.Get(c, "ping").String()
// 4
msg = client.Get(c.Request.Context(), "ping").String()
c.String(http.StatusOK, msg)
})
}> 4 is the right choice.
1 is is kinda wrong because it uses one global context. Usually you want a separate context for each request.
2 creates empty context which kinda pointless.
3 uses Gin context which can't be used as a full replacement for context.Context.https://github.com/go-redis/redis/issues/1594