package main
import (
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"io"
)
// 定义结构
type MsgH struct {
MID MID `json:"id"`
}
type MsgC struct {
MID MID `json:"id"`
}
// 选择了用 uuid 作为 id
type MID uuid.UUID
type UID uuid.UUID
type SID uuid.UUID
type SSEHandle struct {
UID UID
SID SID
handle chan any
}
func main() {
r := gin.Default()
var stream = make(chan any, 2)
var handles = make(chan *SSEHandle, 8)
go func() {
var handleContainer = make(map[UID]map[SID]chan any)
for handle := range handles {
if _, ok := handleContainer[handle.UID]; !ok {
handleContainer[handle.UID] = make(map[SID]chan any)
}
handleContainer[handle.UID][handle.SID] = handle.handle
}
}()
r.GET("/sse", func(c *gin.Context) {
var query = &struct {
Id string `form:"id"`
}{}
err := c.ShouldBind(query)
if err != nil {
return
}
uid, err := uuid.Parse(query.Id)
if err != nil {
return
}
c.SSEvent("message", "hello world")
c.Writer.Flush()
// 现在让每个sse建立时传递UID,并为每个连接单独生成SID。
// 在拥有追踪系统时,可以直接用TraceId作为SID。
var handle = make(chan any, 1)
handles <- &SSEHandle{
UID: UID(uid),
SID: SID(uuid.New()),
handle: handle,
}
c.Stream(func(w io.Writer) bool {
msg, ok := <-handle
if ok {
c.SSEvent("message", msg)
c.Writer.Flush()
}
return ok
})
})
r.POST("/H", func(context *gin.Context) {
var msg = new(MsgH)
err := context.BindJSON(&msg)
if err != nil {
return
}
stream <- msg
})
r.POST("/C", func(context *gin.Context) {
var msg = new(MsgC)
err := context.BindJSON(&msg)
if err != nil {
return
}
stream <- msg
})
_ = r.Run()
}