go基础语法 菜鸟教程 http://www.runoob.com/go/go-tutorial.html

概述一下需求和游戏功能
需求:
1. 接入第三方平台的http请求,数据格式json
2. 可发送多人邮件和全服邮件
3. 多人邮件包括单人邮件,全服邮件包括单服邮件和多服邮件
游戏功能<服务器>:
1. 邮件信息包括:模板id,主题/标题,内容,发送人/署名,类型,附件,收件人,操作途径,离线是否发送
2. 消息流程:第三方请求–>HttpServer—>GameServer

需要留意的几个地方
1. handleSendMail 处理收到的协议包
2. IsHTTPCenter() 如果是中心服务器,则可以向其它HttpServer转发协议包
3. sendMail2GS中CallGameSer向GameServer发送邮件信息包,MailRspPack向HttpServer回包
4. HFWriteRsp 向第三方回包
5. go func() 并行处理向GameServer发包
6. CallGameSer 和 MailRspPack 发包和回包 是顺序执行的 其中MailRspPack 可先挂起等待 直到GameServer返回消息再执行
7. sendGlobalMail2GS全服邮件每隔1s按批次发送邮件,减少服务器同一时间的压力
8. batchSendMail首次向服务器发送邮件时需GameServer创建一个模板id并返回,其它批次发送是需获得这个邮件模板id并把它发给GameServer,并且其它批次不再需要GameServer回包,这样全服邮件就只需创建一个邮件模板即可。batchSendMail返回值依次为:邮件模板id,函数执行结果,数据库查询行索引。只有函数执行成功即发送成功时,下次发送的行索引才可增加。

代码部分
代码中很少有注释,原因:代码的理解不想依赖于注释,想通过好的命名和代码结构让读代码的人也能够理解。有时候过多的注释会降低对代码质量的要求,总想着代码乱点,多写点注释就行了,而不想着如何去精简和优化代码。错误的注释还不如没有注释。只在关键的地方写上注释即可。当然,下面的代码也还有待提高。
body := []byte… 测试用的json数据

package GMimport ("encoding/json""fmt""httpserver/logger""httpserver/misc/packet""httpserver/myDB""httpserver/tylnet""io/ioutil""net/http""time"
)//MailType
const (MailTypeSingle = 0MailTypeMulti  = 1MailTypeServer = 2
)//MailSenderName
const (MailSenderNameGM = "GM"MailSenderNameLD = "官方"
)//MailSenderId
const (MailSenderIDGM = 1MailSenderIDLD = 2
)//MailAttachsMaxNum ..
const MailAttachsMaxNum = 5//MailPlayerIdsMaxNum ..
const MailPlayerIdsMaxNum = 50//SendGlobalMailStep ..
const SendGlobalMailStep = 100//MailAttachXF struct
type MailAttachXF struct {TypeID  int32 `json:"typeId"`GoodsID int32 `json:"goodsId"`Count   int32 `json:"count"`
}//SendMailXF struct
type SendMailXF struct {ID            int            `json:"id"`Title         string         `json:"title"`Content       string         `json:"content"`Sign          string         `json:"sign"`IsGlobal      bool           `json:"isGlobal"`PlayerIds     []uint64       `json:"playerIds"`RegDate       int64          `json:"regDate"`Attaches      []MailAttachXF `json:"attachment"`AreaServerIds []int32        `json:"areaServerIds"`Validity      int            `json:"validity"`
}//SQLPlayerPID struct
type SQLPlayerPID struct {Pid int64 `db:"PID"`
}//MailDataPack send MailDataPack to GameServer
var MailDataPack *tylnet.SendMailPack//MailSendOver ..
var MailSendOver bool = true//batchSendMail send mail in batches
func batchSendMail(bFirstTime bool, mailID uint64, startRow int) (uint64, bool, int) {if !bFirstTime && mailID == 0 {return mailID, false, startRow}if myDB.GameDB == nil {logger.ERR("send mail Err: myDB.GameDB not ready!")return mailID, false, startRow}playerPidData := []SQLPlayerPID{}sql := fmt.Sprintf("SELECT PID FROM player LIMIT %d,%d", startRow, SendGlobalMailStep)err := myDB.GameDB.Select(&playerPidData, sql)if err != nil {logger.ERR("send mail Err: myDB Sql", sql, err.Error())return mailID, false, startRow}if len(playerPidData) == 0 {logger.INFO("send global mail over! mail id =", mailID)return mailID, true, -1}MailDataPack.PidList = nilMailDataPack.PidList = make([]uint64, len(playerPidData))for k, v := range playerPidData {MailDataPack.PidList[k] = uint64(v.Pid)//fmt.Println("player id =", v.Pid, "mail id =", mailID)}MailDataPack.ID = mailIDif bFirstTime {ret := tylnet.CallGameSer(packet.Pack(tylnet.Code["sendmail"], MailDataPack, nil), true)if ret == nil {logger.ERR("send mail Err: golbal mail _callGameSer return nil")return mailID, false, startRow}retPack := tylnet.MailRspPack{}ok := packet.UnPackBuf(&retPack, ret)if !ok {logger.ERR("send mail Err: UnPackBuf return failure")return mailID, false, startRow}//更新mailIDmailID = retPack.MailIDlogger.INFO("send mail success: mail type =", retPack.TypeID, "mail id =", retPack.MailID)} else {tylnet.CallGameSer(packet.Pack(tylnet.Code["sendmail"], MailDataPack, nil), false)}return mailID, true, startRow
}func checkGlobalMailSendOver() bool {return MailSendOver
}func handleSendMail(w http.ResponseWriter, req *http.Request) {body, _ := ioutil.ReadAll(req.Body)//body := []byte(`{"attachment":[{"goodsId":0,"count":100,"typeId":3},{"goodsId":93024,"count":1,"typeId":8},{"goodsId":93025,"count":1,"typeId":8}],"areaServerIds":[102],"isGlobal":true,"sign":"GM","regDate":0,"id":156,"validity":3,"title":"哈哈","playerIds":[1000000000000028],"content":"测试道具"}`)var mailData SendMailXFerr := json.Unmarshal(body, &mailData)if err != nil {logger.ERR(err.Error())tylnet.HFWriteRsp(w, 1, err.Error())return}selfproc := trueif mailData.IsGlobal && tylnet.IsHTTPCenter() {selfproc = tylnet.RedirectOthers(w, req, mailData.AreaServerIds)}if selfproc {sendMail2GS(w, &mailData)}
}func sendMail2GS(w http.ResponseWriter, mailData *SendMailXF) bool {if len(mailData.Attaches) > MailAttachsMaxNum {errStr := "send mail Err: attaches out of max num"logger.ERR(errStr)tylnet.HFWriteRsp(w, 1, errStr)return false}if len(mailData.PlayerIds) > MailPlayerIdsMaxNum {errStr := "send mail Err: player id is out of max num"logger.ERR(errStr)tylnet.HFWriteRsp(w, 1, errStr)return false}if !mailData.IsGlobal && len(mailData.PlayerIds) == 0 {errStr := "send mail Err: this mail need at least one player! "logger.ERR(errStr)tylnet.HFWriteRsp(w, 1, errStr)return false}if !checkGlobalMailSendOver() {errStr := "send mail Err: there are other mails being sent! please try again in a few minutes!"logger.ERR(errStr)tylnet.HFWriteRsp(w, 1, errStr)return false}MailDataPack = &tylnet.SendMailPack{}MailDataPack.ID = 0MailDataPack.SendOffline = 1MailDataPack.Method = -1MailDataPack.Theme = mailData.TitleMailDataPack.Content = mailData.Contentif mailData.IsGlobal {MailDataPack.TypeID = MailTypeServer} else {MailDataPack.TypeID = MailTypeMulti}if mailData.Sign == MailSenderNameGM {MailDataPack.Sender = MailSenderIDGM} else {MailDataPack.Sender = MailSenderIDLD}MailDataPack.Attaches = make([]tylnet.MailAttach, len(mailData.Attaches))for k, v := range mailData.Attaches {MailDataPack.Attaches[k].TypeID = v.TypeIDMailDataPack.Attaches[k].GoodsID = v.GoodsIDMailDataPack.Attaches[k].Count = v.Count}MailDataPack.PidList = make([]uint64, len(mailData.PlayerIds))for k, v := range mailData.PlayerIds {MailDataPack.PidList[k] = v}go func() {if mailData.IsGlobal {sendGlobalMail2GS} else {sendMultiMail2GS()}}()tylnet.HFWriteRsp(w, 0, "")return true
}func sendGlobalMail2GS() {MailSendOver = falsevar mailID uint64startRow := 0bSend := truebFirstTime := truefor true {if startRow == -1 {break}rowRefer := 0mailID, bSend, rowRefer = batchSendMail(bFirstTime, mailID, startRow)if bSend {if rowRefer == -1 {startRow = rowRefer} else {startRow += SendGlobalMailStep}} else {startRow = rowRefer}bFirstTime = falsetime.Sleep(time.Second)}MailSendOver = true
}func sendMultiMail2GS() {ret := tylnet.CallGameSer(packet.Pack(tylnet.Code["sendmail"], MailDataPack, nil), true)if ret == nil {logger.ERR("send mail Err: _callGameSer return nil")return}retPack := tylnet.MailRspPack{}ok := packet.UnPackBuf(&retPack, ret)if !ok {logger.ERR("send mail Err: UnPackBuf return failure")return}logger.INFO("send mail success: mail type =", retPack.TypeID, "mail id =", retPack.MailID)
}

go语言实现的GM邮件功能:全服邮件和多人邮件的发送相关推荐

  1. 测试服务器角色转移系统,角色转移功能全服开放

    大福利:角色转移功能即将全服开放 经过长时间的测试和评估,角色转移功能即将和大家见面,勇士们是不是特别期待呢.特别急于转移呢?话不多说,今天小编就带大家来看一下角色转移的秘密吧. 1.找到比奇NPC户 ...

  2. php 读取 eml,PHP 实现下载邮件功能,保存为eml格式

    引言:因为业务需求,需要获取订单的往来邮件,其中涉及到下载邮件功能.由于腾讯企业邮箱API接口不支持下载邮件功能,只能自己写. 获取邮件内容,保存到数据库 步骤略:网上有很多现成的,利用imap来获取 ...

  3. 邮件 查看html源码,微软 Win10解决邮件显示HTML源代码的问题

    Win10邮件显示HTML源代码怎么办?Win10有个邮件功能,可以在电脑上收发邮件,是办公生活的好助手.但是有朋友在使用Win10邮件的时候发现邮件不显示内容,显示的是HTML源代码,这是什么情况呢 ...

  4. 微信大更新,黄脸表情会动了,还能炸群!还有状态、浮窗...张小龙剧透的功能全来了...

    1月21日,微信在十岁生日这天,正式向iOS用户推送了8.0版本.张小龙前天在微信公开课上剧透的几个小功能,也一一出现在新版微信中. 会动的表情.微信个人状态.浮窗......在1月19日的微信公开课 ...

  5. 前后端、多语言、跨云部署,全链路追踪到底有多难?

    作者|涯海 全链路追踪的价值 链路追踪的价值在于"关联",终端用户.后端应用.云端组件(数据库.消息等)共同构成了链路追踪的轨迹拓扑大图.这张拓扑覆盖的范围越广,链路追踪能够发挥的 ...

  6. 邮件发送类_10 分钟实现 Spring Boot 发生邮件功能

    基础知识 什么是SMTP? 什么是IMAP? 什么是POP3? IMAP和POP3协议有什么不同呢? 进阶知识 什么是JavaMailSender和JavaMailSenderImpl? 如何通过Ja ...

  7. 安卓调用系统语音识别功能全解(谷歌语音服务):获取识别结果,使用语音识别进行搜索。

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓调用系统语音识别功能全解(谷歌语音服务):获取识别结果,使用语音识别进行搜索. 首先要添加权限 <uses-permission andro ...

  8. 安卓短信功能全解:调用系统短信功能发送短信、彩信,使用SmsManager发送短信,并监听发送短信的投递情况,使用广播接收器监听接收的短信。

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓短信功能全解:调用系统短信功能发送短信.彩信,使用SmsManager发送短信,并监听发送短信的投递情况,使用广播接收器监听接收的短信. 首先需要 ...

  9. 北华大学c语言题库百度云,北华大学C语言题库精简打印版(全).doc

    北华大学C语言题库精简打印版(全).doc 北华大学C语言题库精简打印版(全)一.判断题 - 正确篇1.字符常量的长度肯定为1.Y2.在调用函数时,实参把值传送给对应位置上的形参,形参的值不能传给实参 ...

最新文章

  1. kubeadm 线上集群部署(四) k8s node 节点初始化安装
  2. 编程小白的第一本python入门书-《编程小白的第一本Python入门书》读书笔记
  3. 使用Adsutil.vbs来获取IIS用户的密码
  4. 北京内推 | 启元实验室招聘视觉感知算法工程师(北京事业单位)
  5. highcharts 怎么去掉鼠标悬停效果_练瑜伽减肥没效果什么原因?
  6. 合同相似可逆等价矩阵的关系及性质_笔记:辛矩阵和Siegel上半平面
  7. Spring4.x(14)---SpringEL-运算符
  8. 性能测试之二——性能测试的流程
  9. python查找文件夹下所有文件_如何用Python实现查找/目录下的文件夹或文件,致谢...
  10. 环,模,补码,负数的表示与减法实现
  11. STM32:配置定时器为PWM输出模式以及编码器接口模式
  12. 惠普战66拆机加固态_惠普战66测评:想要提高办公效率,惠普是你的品质之选...
  13. IPD产品开发流程详解
  14. android fragment 设置透明,DialogFragment背景透明设置
  15. java后端简历项目经历_简历上的项目经历怎么写 ?这 3 条原则不可忽视 !
  16. opencv 视频格式
  17. Python代码解析LRC歌词文件
  18. 计算机老师教师节祝福语,送给老师教师节祝福语
  19. lua在线手册 lua在线lua学习教程 lua参考手册中文翻译
  20. python获取pdf页数_Python分割指定页数的pdf文件方法

热门文章

  1. HTML播放视频(兼容IE低版本)
  2. 业务安全 –业务逻辑漏洞
  3. 驱动开发:内核取ntoskrnl模块基地址
  4. 【文件导出】vue中使用post文件导出
  5. [转]屏幕录相专家常见问题
  6. 全双工模式和半双工模式的区别
  7. 小马智行「下沉」市场,L4级自动驾驶「回归」车企赛道
  8. 题解 | 2023河南萌新联赛第(四)场:河南大学 解题报告
  9. 【移动安全高级篇】————12、静态分析
  10. 线性代数让我想想:克拉默法则