GO 基于gorilla websocket实现点餐系统(一阶)

点餐系统(一阶)

简言

一阶为入门,画出大概"轮廓",后面几阶在进行逐步填充,添加细节和上色🎨,这篇文章算是我上一篇<基于gorilla websocket搭建聊天室>的接龙,这里的代码也是那篇文章代码的继续
本阶将会实现

  • 客户点菜
  • 厨师实时收到客户点餐
  • 客户状态(是否结账,当前用餐金额)

客户吃饭流程
请添加图片描述
整个点餐系统的运作流程
请添加图片描述
请添加图片描述
数据库表构造
请添加图片描述

基本依赖

var customerpool = make(map[*Connection]*userinfo)
var dishespool = make(map[*singledish]bool) //菜单池,false表示点单未出单,true表示出单
var ordhub = &OrderHub{SendToChef: make(chan *singledish)}
var chefpool = make(map[*Connection]struct{})
// order system
type order struct {
	Header string `json:"header"`
	Dish   int    `json:"dish"`
}

// 记录点菜的客户讯息
type userinfo struct {
	Id      int     `json:"id"`      //用于识别客户的id
	OrderId int     `json:"orderid"` //客户点菜的菜单id,一个客户可以持有多份菜单,一个菜单可持有一份以上的菜,结算以每份菜单具体金额为准
	Sum     float32 `json:"sum"`     //客户一共需要结算的金额
	Status  bool    `json:"status"`  //客户是否买单
	Action  string  `json:"action"`  //记录客户的所有点菜操作
}
type singledish struct {
	Name string
	time string
}
type aboutdish struct {
	Name  string
	Price float32
	Id    int
}
type OrderHub struct {
	SendToChef chan *singledish
}

点菜服务

func OrderSomething(w http.ResponseWriter, r *http.Request) {
	upgrade.CheckOrigin = func(r *http.Request) bool { return true }
	ws, err := upgrade.Upgrade(w, r, nil)
	if err != nil {
		errorlog.Println(err)
	}
	con := &Connection{con: ws, send: make(chan []byte, 256)}
	hub.register <- con
	defer func() {
		hub.unregister <- con
		ws.Close()
	}()
	Waiter(con)
}
func Waiter(con *Connection) {
	var orderinfo order
	for {
		err := con.con.ReadJSON(&orderinfo)
		if err != nil {
			errorlog.Println("read from connection failed,", err)
		} else {
			//debug zone
			if _, ok := customerpool[con]; !ok {
				fmt.Println("connection dont exsit")
				id := rand.Intn(89999) + 10000
				orderid := rand.Intn(899999) + 100000
				customerpool[con] = &userinfo{Id: id, OrderId: orderid, Sum: 0, Action: ""}
			}
			//end
			userorderinfo := customerpool[con]
			fmt.Println(userorderinfo) //debug line
			price, actionid := getdishinfo(orderinfo.Dish)
			fmt.Println(price) //debug line
			userorderinfo.Sum += price
			userorderinfo.Action += actionid + "\n"
			//这里还应有一个推送功能,用于将新点菜品发送给后厨端
			dish := new(singledish)
			dish.ScanAction(actionid)
			dish.PushToPool()
			ordhub.SendToChef <- dish
		}
		con.send <- []byte("im live")
	}
}
func getdishinfo(id int) (float32, string) {
	//从数据库中获取菜品讯息
	dbcon, err := sql.Open("mysql", "test:123456@tcp(127.0.0.1)/lab?charset=utf8")
	if err != nil {
		errorlog.Println(err)
		return -1, ""
	}
	defer dbcon.Close()
	var dishinfo aboutdish
	dishinfo.Id = id
	err = dbcon.QueryRow("select price,name from ordersystem where id =?", id).Scan(&dishinfo.Price, &dishinfo.Name)
	if err != nil {
		errorlog.Println(err)
	}
	//操作id=下单时间+菜品名称+菜品id
	actionid := time.Now().Format(time.Kitchen) + "&" + dishinfo.Name + "&" + strconv.Itoa(dishinfo.Id)
	return dishinfo.Price, actionid
}

这里的操作ID是很重要的,他包含了客户点某个菜品的时间,点的什么菜,菜品id(菜品唯一的识别标志,可能同一个菜有多个版本,他们菜名和价格相同,菜品id就可以区分它们之间的版本来告诉后厨客人对于这道菜到底要哪种做法),操作id将会保存起来以供日后使用或分析。

厨师端

一阶厨师端很简单,不用实现任何功能,挂起接收前台订单就行了,后面几阶会对厨师端进行或多或少的强化

func ChefPlatform(w http.ResponseWriter, r *http.Request) {
	upgrade.CheckOrigin = func(r *http.Request) bool { return true }
	ws, err := upgrade.Upgrade(w, r, nil)
	if err != nil {
		errorlog.Println("establish connection with chef failed", err)
	}
	con := &Connection{con: ws, send: make(chan []byte, 256)}
	chefregister <- con
	defer func() {
		chefunregister <- con
		ws.Close()
	}()
	for {
		con.send <- []byte("im live")
	}
}
websocket必备注册机

这里的注册机是上篇聊天室注册机增强版(在保留了聊天室原有的注册机制上,新增客户注册和厨师注册)

type Hub struct {
	register      chan *Connection
	unregister    chan *Connection
	customer      chan *Connection
	clearcustomer chan *Connection
	Broadcast     chan []byte
}
var chefregister = make(chan *Connection)
var chefunregister = make(chan *Connection)
func (s *Hub) Run() {
	fmt.Println("start register machine")
	for {
		rand.Seed(time.Now().UnixNano())
		select {
		case c := <-s.register:
			conpool[c] = struct{}{}
			fmt.Println("register connection")
		case c := <-s.unregister:
			if _, ok := conpool[c]; ok {
				delete(conpool, c)
				fmt.Println("unregister connection")
			}
		//order system zone start
		case c := <-s.customer:
			conpool[c] = struct{}{}
		case c := <-s.clearcustomer:
			if _, ok := conpool[c]; ok {
				delete(conpool, c)
			}
			if _, ok := customerpool[c]; ok {
				delete(customerpool, c)
			}
		//order system zone end
		//chef zone start
		case c := <-chefregister:
			conpool[c] = struct{}{}
			chefpool[c] = struct{}{}
			processlog.Println("register a chef")
		case c := <-chefunregister:
			if _, ok := chefpool[c]; ok {
				delete(chefpool, c)
				processlog.Println("unregister a chef")
			}
			if _, ok := conpool[c]; ok {
				delete(conpool, c)
			}
		case c := <-ordhub.SendToChef:
			for con, _ := range chefpool {
				err := con.con.WriteJSON(c)
				errorlog.Println(err)
			}
		//chef zone end
		case m := <-s.Broadcast:
			for clients := range conpool {
				select {
				case clients.send <- m:
				default:
					delete(conpool, clients)
					fmt.Println("delete connection")
				}
			}
		}
	}
}
测试
func ServerStart() {
	go hub.Run()
	http.HandleFunc("/chat", ChatRoom)
	http.HandleFunc("/orderdish", OrderSomething)
	http.HandleFunc("/chef", ChefPlatform)
	http.ListenAndServe(":8001", nil)
}

postman
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值