自动推送消息后台

简介:

是一个定时给教师推送教务信息的后台程序,定时推送功能由Go的cron库来实现,定时调用自己写的teacher_noti方法,并且对外开放接口,可以在外面实现推送内容的增删改查。

 

学到的新技术:

  1. 第一次了解到crontab和接触到cron库,掌握了crontab的定时表达式

    crontab.AddFunc("* * * * *", test) //五个*号分别表示分,时,天,月,星期

    AddFunc方法具有局限性,传入的方法不能带有参数,如果一定要带参数可以用AddJob方法

    crontab.AddJob("* * * * *", Job{})  //Job是一个实现了Run方法的类
  2. 获取id、状态等int类型的数据时,最好在外面封装一层

    state := ParseIntDefault(c.PostForm("state"), 0)


    func ParseIntDefault(s string, d int) int {
    if a, err := strconv.Atoi(s); err == nil {
    return a
    }
    return d
    }
  3. 返回数据给前端时要注意格式,int类型要转string,time类型要format,还要做好数据可能为空的处理。这里最好写个Assemble方法(用接口实现多态),要传入指针数据类型

    // Assembler 将 model 组装成 map
    type Assembler interface {
    Assemble() map[string]interface{}
    }

    // StructToMap 返回 map
    func StructToMap(a Assembler) map[string]interface{} {
    return a.Assemble()
    }

    func (item *NotiForm) Assemble() map[string]interface{} {
    data := map[string]interface{}{}
    data["noti_id"] = strconv.Itoa(item.ID)
       
       //...

       //使用ParseIntDefault方法后,若传入数据无效会自动校正为0
    if item.End.IsZero() {
    data["end"] = ""
    } else {
    data["end"] = item.End.In(cstlocGlobal).Format("2006-01-02 15:04:05")
    }

    return data
    }

     

低级错误:

  1. 在使用反射方法纠错时没有写errname

    errStrings := []string{}
    t := reflect.TypeOf(notiForm)
    for i := 0; i < t.NumField(); i++ {
    if strings.Contains(err.Error(), t.Field(i).Name) {
    errname := t.Field(i).Tag.Get("errname")
    errStrings = append(errStrings, errname+"未填写或有误")
    }
    }
  2. 项目中很多地方纠错就用了log打印一下,没有给前端返回消息或者及时return

  3. 重复连接数据,只要设置全局变量,然后在main方法中连接一次即可

  4. 颜色要用美式英语color

 

理解错误:

  1. 数据库表建多余了,对表功能的理解不够,下次建表前要想想清楚(及时问leader)

  2. 在统计成功发送数量时,想到的是往发送方法中传入一个int遍历的指针,每次成功发送后都++。后改为给该方法添加一个bool返回值,外层使用for循坏判断++

     

对Go语言接口实现多态的理解:

go语言使用struct和interface实现多态

type Cat struct{
   Name string
}

type Dog struct{
   Name string
}

//1. 创建一个接口,指定要实现的方法
type animaler interface {
   eat()
   sleep()
}

//2. 实现接口中的方法 (要将接口中的方法全部实现)
func (cat Cat) eat() {
   fmt.Println(cat.Name,"eat")
}
func (cat Cat) sleep() {
   fmt.Println(cat.Name,"sleep")
}

func (dog Dog) eat() {
   fmt.Println(dog.Name,"eat")
}
func (dog Dog) sleep() {
   fmt.Println(dog.Name,"sleep")
}

//3. 创建一个方法传入接口
func TestInterface(a animaler) {
   a.eat()
   a.sleep()
}

//4. 使用时调用方法TestInterface()
var cat Cat
cat.Name = "mimi"

var dog Dog
dog.Name = "wangwang"

TestInterface(cat) //定义时入参时为animaler类型,调用时入参为实现了接口方法的实体类类型
TestInterface(dog)

接口中有一些方法,只要某结构体实现了该接口中的所有方法,该结构体的实体就能作为已该接口为入参的入参

posted @ 2021-12-15 11:36  临卓  阅读(157)  评论(0编辑  收藏  举报