CodeSection0

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()
}