用golang写了个统计各单位报送的信息数量的微服务

用golang写了个统计各单位报送的信息数量的微服务,第1张

概述代码很乱,bug很多,将就着看吧。参考了很多网上代码,只能说声感谢了。 //cjl.ZongHeInfo.1.0//目的:对各部门报上来的信息数量进行排名//思路:预计一年信息量不超过100M,全部存入全局变量GlobalInfoDoc中,以方便排序,统计//在协程中每5分钟将GlobalInfoDoc用json编码后存入文件中。因此,退出程序前应先手动保存(一定程度上可考虑用sign

代码很乱,BUG很多,将就着看吧。参考了很多网上代码,只能说声感谢了。

//cjl.ZongHeInfo.1.0//目的:对各部门报上来的信息数量进行排名//思路:预计一年信息量不超过100M,全部存入全局变量Globalinfodoc中,以方便排序,统计//在协程中每5分钟将Globalinfodoc用Json编码后存入文件中。因此,退出程序前应先手动保存(一定程度上可考虑用signal),避免5分钟内的数据丢失//重要:生成的Json备份文件不能用notepad编辑,要保存为UTF-8 NO BOMpackage mainimport (    "io/IoUtil"    "math"    "net/url"    "strconv"    //"enCoding/base64"    "enCoding/Json"    "fmt"    "log"    "sort"    "strings"    "sync"    "net/http"    "os"    "os/exec"    "time")var (    DEPA              = []string{"XX部","XXX部","X1部","X2部","XX公司","XX厂","XXX厂","XX中心"}    Globalinfodoc     TInfodoc                  //保存了所有报上来的信息,其实就相当于一个文本文件    GlobalConf        = make(map[string]string) //配置文件    GlobalManuscripts = ""                      //约稿要求,直接放投稿页面的placeholder中了)type TInfodoc struct {    Infos        []TInfo //属性名一定要大写,血的教训    sync.RWMutex         //http是多线程的,加上锁}type TInfo struct {    Time       int64  `Json:"name,omitempty"`       //`时间`    Title      string `Json:"Title,omitempty"`      //`标题`    Content    string `Json:"Content,omitempty"`    //`内容`    Department string `Json:"Department,omitempty"` //`单位`    Who        string `Json:"Who,omitempty"`        //`报送人`    Tel        string `Json:"Tel,omitempty"`        //`电话`    Ip         string `Json:"IP,omitempty"`         //IP}//原计划利用cookie保存,后来认为用不上,把相关代码注释掉了type TUser struct {    name string    Tel  string}//用于对所报的信息按单位名称排序type TInfoRanks []TInfoRanktype TInfoRank struct {    Key   string    Value int}func main() {    //打开文件,若文件不存在则生成    year,_,_ := time.Now().Date()    fname := "info" + strconv.Itoa(year)    f,_ := os.Openfile(fname,os.O_RDWR|os.O_CREATE,0755)    //将文件内容反序列化到全局变量infodoc    out,_ := IoUtil.ReadAll(f)    //fmt.Println(string(out))    Json.Unmarshal(out,&Globalinfodoc)    //这里不能用defer f.Close(),因为main函数不会结束    f.Close()    //fmt.Println(infodoc)    http.HandleFunc("/Add",Add)    http.HandleFunc("/Add2",Add2)    http.HandleFunc("/List",List)    http.HandleFunc("/save",save)    http.HandleFunc("/conf",conf)    http.HandleFunc("/yg",Manuscripts)    http.HandleFunc("/",Index)    exec.Command("cmd","/c","C:\Progra~2\Google\Chrome\Application\Chrome.exe","http://localhost:8000/Add").Run()    go savefile()    fmt.Println("因5分钟才保存一次文件,所以退出程序前请访问/save以防止最近5分钟提交的信息丢失")    fmt.Println("请访问/conf更新配置文件的allowip")    http.ListenAndServe(":8000",nil)}func checkErr(err error) {    if err != nil {        log.Println(err)    }}func Index(w http.ResponseWriter,r *http.Request) {    s := `    <!DOCTYPE HTML><HTML><head> <Meta charset="utf-8"> <Title></Title> <style type="text/CSS">a:link,a:visited{ text-decoration:none;  /*超链接无下划线*/ color:red;}a:hover{ text-decoration:underline;  /*鼠标放上去有下划线*/}</style></head><body>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://192.168.0.239:8000/Add" target="_blank">信息报送</a></body></HTML>    `    fmt.Fprintf(w,s)}func Add(w http.ResponseWriter,r *http.Request) {    //模板    tpl := `<!DOCTYPE HTML><HTML><head> <Meta charset="utf-8"> <Title></Title> <style>input{    wIDth:500px;}textarea{    wIDth:500px;}.labelspan{    display:inline-block;    wIDth:80px;}.input2{    wIDth:410px;}</style></head><body onload="JavaScript:init()"><form action="Add2" method="post" onsubmit="return check()"><fIEldset><legend><a href="yg">_</a>信息汇报<a href="List">_</a></legend>标题: <input ID="Title" name="Title" type="text" size="30" required="required"><br/>内容: <textarea ID="Content"   name="Content"   rows="15" placeholder="{{Manuscripts}}" required="required"></textarea><br/>正文限制(100-1000字):<span ID="txtNum">0</span><br/>部门(单位): <select ID="Department" name="Department" required="required"><option value="">请选择</option>{{OPTIONS}}</select><br><span class="labelspan">报 送 人:</span> <input ID="Who"  name="Who" class="input2"  value="" type="text" size="30" required="required"><br/><span class="labelspan">联系电话:</span> <input ID="Tel" name="Tel"  class="input2"  value="" type="text" size="30" required="required"><br/><input type="submit" value="提交"></fIEldset></form>{{SORTList}}<script>var txt = document.getElementByID("Content"); var txtNum = document.getElementByID("txtNum"); txt.addEventListener("keyup",function(){ txtNum.textContent = txt.value.length; })</script><script>     function check(){        var Title = document.getElementByID("Title").value;        var Content = document.getElementByID("Content").value;            var Department = document.getElementByID("Department").selectedindex;            var Who = document.getElementByID("Who").value;        var Tel = document.getElementByID("Tel").value;         if(Title ==  null || Title == ‘‘ ||Title.length <6){              alert("请完善标题!");              return false;         }else if(Content.length <100||Content.length >1000){             alert("正文限制100至1000字!");              return false;        }else if(Department == 0){             alert("请选择部门!");              return false;        }else if(Who.length <2){             alert("请填写正确的姓名!");              return false;        }else if(Tel.length <7){             alert("请填写联系电话!");              return false;        }                     return true;      }</script>    <script>    function init(){        self.moveto(0,0);    self.resizeto(screen.wIDth,screen.height);}    </script></body></HTML>`    //读cookie  注意:直接读来自用户的数据不安全    /*        var User TUser        u,err := r.cookie("u")        if err == nil {            uu,_ := base64.StdEnCoding.DecodeString(u.Value)            Json.Unmarshal(uu,&User)        }        //fmt.Println(User)        tpl = strings.Replace(tpl,`{{WHO}}`,string(User.name),-1)        tpl = strings.Replace(tpl,`{{TEL}}`,string(User.Tel),-1)    */    //选项    var options strings.Builder    for _,v := range DEPA {        fmt.Fprintln(&options,`<option value="`,v,`">`,`</option>`)    }    //fmt.Println(options.String())    //统计    year,month,_ := time.Now().Date()    //统计各部门稿件数量的map    //本月    thisMonthFirstDay := time.Date(year,1,0,time.Local) //本月第一天    nextMonthFirstDay := thisMonthFirstDay.AddDate(0,0)                //下月第一天    _ThisMonth := periodInfos(thisMonthFirstDay,nextMonthFirstDay)    //上月    lastMonthFirstDay := thisMonthFirstDay.AddDate(0,-1,0) //上月第一天    _LastMonth := periodInfos(lastMonthFirstDay,thisMonthFirstDay)    //本年    thisYearFirstDay := time.Date(year,time.Local) //本年第一天    nextYearLastDay := thisYearFirstDay.AddDate(1,0)              //明年第一天    _ThisYear := periodInfos(thisYearFirstDay,nextYearLastDay)    //将map转切片,用sort.Slice排序后输出    var sortList strings.Builder    s_ThisMonth := sortByValue(_ThisMonth)    s_LastMonth := sortByValue(_LastMonth)    s_thisYear := sortByValue(_ThisYear)    //本月ol    fmt.Fprintln(&sortList,`<table><tr><th>本月排序</th><th>上月排序</th><th>本年排序</th><tr><td>`)    fmt.Fprintln(&sortList,`<ol>`)    for _,v := range s_ThisMonth {        fmt.Fprintln(&sortList,`<li>`,v.Key,v.Value,`篇`,`</li>`)    }    //上月ol    fmt.Fprintln(&sortList,`</ol></td><td><ol>`)    for _,v := range s_LastMonth {        fmt.Fprintln(&sortList,`</li>`)    }    //本年ol    fmt.Fprintln(&sortList,v := range s_thisYear {        fmt.Fprintln(&sortList,`</li>`)    }    fmt.Fprintln(&sortList,`</ol></td></tr></table>`)    //替换模板    tpl = strings.Replace(tpl,`{{OPTIONS}}`,options.String(),-1)    tpl = strings.Replace(tpl,`{{SORTList}}`,sortList.String(),`{{Manuscripts}}`,GlobalManuscripts,-1)    //模板输出    fmt.Fprintln(w,tpl)}//对报送的稿件数量排序func sortByValue(m map[string]int) TInfoRanks {    pl := make(TInfoRanks,len(m))    i := 0    for k,v := range m {        pl[i] = TInfoRank{k,v}        i++    }    sort.Slice(pl,func(i,j int) bool {        flag := false        if pl[i].Value > pl[j].Value {            flag = true        } else if pl[i].Value == pl[j].Value {            if pl[i].Key < pl[j].Key {                flag = true            }        }        return flag    })    return pl}func Add2(w http.ResponseWriter,r *http.Request) {    //r.ParseForm()    if r.Method == "POST" {        info := TInfo{}        info.Time = time.Now().Unix()        info.Title = safeFilter(r.PostFormValue("Title"))        info.Content = safeFilter(r.PostFormValue("Content"))        info.Department = safeFilter(r.PostFormValue("Department"))        info.Who = safeFilter(r.PostFormValue("Who"))        info.Tel = safeFilter(r.PostFormValue("Tel"))        ip := r.RemoteAddr        info.Ip = ip[0:strings.LastIndex(ip,":")]        //在全局Infodoc的Info切片后追加info        Globalinfodoc.Lock()        Globalinfodoc.Infos = append(Globalinfodoc.Infos,info)        Globalinfodoc.Unlock()        //设置cookie        //base64        /*            u := TUser{}            u.name = info.Who            u.Tel = info.Tel            us,_ := Json.Marshal(u)            uu := base64.StdEnCoding.EncodetoString(us)            cookieu := http.cookie{name: "u",Value: uu,Path: "/",MaxAge: 86400 * 180}            http.setcookie(w,&cookieu)        */        //重定向,避免用户重复提交        http.Redirect(w,r,"Add",http.StatusFound)        return    }    //不允许GET访问    fmt.Fprintln(w,"what are you 弄啥哩!")}func List(w http.ResponseWriter,r *http.Request) {    ip := r.RemoteAddr    ip = ip[0:strings.LastIndex(ip,":")]    allowip := GlobalConf["allowip"]    if !strings.Contains(allowip,ip) {        fmt.Fprintln(w,"not allow")        return    }    tpl := `<HTML><head>        <Meta charset="UTF-8">        <Title></Title>         <style type="text/CSS">          body{background-color:#f0f0f0;}            table{    wIDth:1000px;    table-layout:fixed;/* 只有定义了表格的布局算法为fixed,下面td的定义才能起作用。 */}td{    wIDth:100%;    min-wIDth:300px;    word-break:keep-all;/* 不换行 */    white-space:nowrap;/* 不换行 */    overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */    text-overflow:ellipsis;/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用*/}ul{    border:1px solID #000;}li{    word-break:break-all;}  .ctx{background-color:#f0f0f9;}        </style>    </head>       <body>       {{TB}}        {{PAGENAV}}</body></HTML>`    //获取用户输入url参数?p=1中的页码1    uri,_ := url.Parse(r.RequestURI)    urlParam := uri.Rawquery    uri_m,_ := url.Parsequery(urlParam)    curpage := 1   //设当前页为1    p_uri_int := 1 //用户提供的页码,默认为1    uri_m_p,ok := uri_m["p"]    if ok {        p_uri_int,_ = strconv.Atoi(uri_m_p[0])    }    perpage := 1000 //每页1000条    numall := len(Globalinfodoc.Infos)    if numall <= 0 {        fmt.Fprintln(w,"无数据")        return    } //总信息数    maxpage := int(math.Ceil(float64(numall) / float64(perpage))) //末页    if p_uri_int <= 0 {        curpage = 1    } else if p_uri_int > maxpage {        curpage = maxpage    } else {        curpage = p_uri_int    }    pagenav := `<a href=List>首页</a> <a href=List?p=` + strconv.Itoa(curpage-1) + `>上一页</a> <a href=List?p=` + strconv.Itoa(curpage+1) + `>下一页</a> <a href=List?p=` + strconv.Itoa(maxpage) + `>尾页</a>`    //以ul>li方式输出表格    var sb strings.Builder    //逆序输出1000条,最新的稿件显示在最上面    start1000 := numall - (curpage-1)*1000    end1000 := numall - curpage*1000 + 1 //如:从1001到2000,而不是1000到2000,所以加1    if end1000 < 1 {        end1000 = 1 //逆序输出,最后一条也就是第一条    }    for i := start1000; i >= end1000; i-- {        info := Globalinfodoc.Infos[i-1] //第一条对应的索引为0,所以减1        time1 := time.Unix(int64(1553254972),0).Format("2006-01-02 15:04:05")        fmt.Fprintln(&sb,`<ul>`)        fmt.Fprintln(&sb,`ID:`,i,`</li>`)        fmt.Fprintln(&sb,time1,info.Title,`<li class="ctx">`,info.Content,info.Department,info.Who,info.Tel,info.Ip,`</ul>`)    }    //替换模板    tpl = strings.Replace(tpl,`{{TB}}`,sb.String(),`{{PAGENAV}}`,pagenav,-1)    fmt.Fprintln(w,tpl)}func save(w http.ResponseWriter,r *http.Request) {    savefile()}//保存Globalinfodoc,每5分钟保存一次func savefile() {    t1 := time.Tick(300 * time.Second)    for {        select {        case <-t1:            //fmt.Println("t1定时器")            year,_ := time.Now().Date()            fname := "info" + strconv.Itoa(year)            //文件不存在则创建            _,_ = os.Openfile(fname,0755)            out,_ := Json.Marshal(Globalinfodoc)            IoUtil.Writefile(fname,out,os.ModeExclusive)        }    }}//安全过滤字符串func safeFilter(s string) string {    s = strings.Replace(s,`=`,`=`,-1)    s = strings.Replace(s,``,`’`,-1)    s = strings.Replace(s,`"`,`”`,`<`,`〈`,`>`,`〉`,string(byte(10)),`<br>`,-1)    return s}//统计一段时间内的稿件数量排名func periodInfos(t1,t2 time.Time) map[string]int {    m := make(map[string]int,len(DEPA))    for _,v := range DEPA {        m[v] = 0    }    //更新投稿数量    for _,info := range Globalinfodoc.Infos {        dp := strings.Trimspace(info.Department) //这里将字符串转[]byte后发现前后有空格,asii为32        if _,ok := m[dp]; ok {            if info.Time >= t1.Unix() && info.Time < t2.Unix() {                m[dp]++            }        }    }    return m}//读配置文件func conf(w http.ResponseWriter,r *http.Request) {    //配置文件中每行的格式类似:a=1    //将a=1解析到map中,k为等号左边的a,v为等号右边的1    var m = make(map[string]string,0)    fname := "conf.txt"    //文件不存在则创建    f,_ := os.Openfile(fname,0755)    defer f.Close()    if si,_ := f.Stat(); si.Size() == 0 {        f.WriteString("allowip=[::1],192.168.3.4,192.168.2.4")    }    b,_ := IoUtil.Readfile(fname)    c := strings.Split(string(b),"\n")    for _,v := range c {        if v != "" {            d := strings.Split(v,"=")            m[d[0]] = d[1]        }    }    var l *sync.Mutex    l = new(sync.Mutex)    l.Lock()    defer l.Unlock()    GlobalConf = m}//设置约稿内容func Manuscripts(w http.ResponseWriter,r *http.Request) {    ip := r.RemoteAddr    ip = ip[0:strings.LastIndex(ip,"not allow")        return    }    //输入录入页面    if r.Method == "GET" {        tpl := `    <HTML>    <head>    <Meta charset="utf-8">     <Title></Title></head>    <body>    <form action="" method="POST">    <textarea ID="yg" name="yg" rows=15 cols=50 value="" >{{Manuscripts}}</textarea>    <input type="submit" value="提交">    </form>    </body>    </HTML>    `        //替换模板        tpl = strings.Replace(tpl,-1)        fmt.Fprintln(w,tpl)        return    } else if r.Method == "POST" {        s := r.PostFormValue("yg")        var l *sync.Mutex        l = new(sync.Mutex)        l.Lock()        defer l.Unlock()        GlobalManuscripts = s        //同时将约稿内容保存为yg.txt  如果用IoUtil.Writefile,则os.ModeAppend是无效的        //outil.Writefile("yg.txt",[]byte(s),os.ModeAppend)        fl,err := os.Openfile("yg.txt",os.O_APPEND|os.O_CREATE,0644)        if err != nil {            return        }        defer fl.Close()        fl.Write([]byte(s))        //重定向,避免用户重复提交        http.Redirect(w,http.StatusFound)        return    } else {        fmt.Fprintln(w,"what are you 弄啥哩!")    }}
总结

以上是内存溢出为你收集整理的用golang写了个统计各单位报送的信息数量的微服务全部内容,希望文章能够帮你解决用golang写了个统计各单位报送的信息数量的微服务所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1268370.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-08
下一篇2022-06-08

发表评论

登录后才能评论

评论列表(0条)

    保存