初识golang

逻辑如下:

程序开启http服务器接收请求,且每隔20秒查询一次表auto_backup中flag为0的值,如果有查到且计划执行时间小于当前时间,则将表to_do的数据抓出来,通过邮件发送,完成后将数据表flag update 为1

表结构:

MySQL []> desc auto_backup;
+----------+---------------+------+-----+---------+----------------+
| Field    | Type          | Null | Key | Default | Extra          |
+----------+---------------+------+-----+---------+----------------+
)       | NO   | PRI | NULL    | auto_increment |
)       | NO   |     | NULL    |                |
) | NO   |     | NULL    |                |
)       | NO   | MUL | NULL    |                |
+----------+---------------+------+-----+---------+----------------+
 rows in set (0.04 sec)

表数据:

MySQL []> SELECT
    -> `id`,
    -> FROM_UNIXTIME(`auto_backup`.`datetime`) AS `datetimes`,
    -> `auto_backup`.`to_do` AS `to_do`,
    -> `auto_backup`.`flag` AS `flag`
    -> FROM
    -> `auto_backup`
    -> order by datetimes desc
    ;
+----+---------------------+-----------------+------+
| id | datetimes           | to_do           | flag |
+----+---------------------+-----------------+------+
  ::  |
+----+---------------------+-----------------+------+
 row in set (0.04 sec)

效果如下:

添加记录

发送记录

服务器log:

代码如下:

package main

// 导入相关包
import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "gopkg.in/gomail.v2"
    "log"
    "net/http"
    "strconv"
    "time"
)

// http 服务器
func Httpd_beiwang(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()

    // 赛选掉访问的url路径为 /favicon.ico
    if "/favicon.ico" != r.URL.Path {
        log.Println(r.Form)

        // 获取url参数
        time_value, timeOK := r.Form["time"]
        beiwang_value, beiwangOK := r.Form["beiwang"]

        // 如果两个参数正确,则判断参数正确,需要将定时任务写到数据库中去
        if timeOK && beiwangOK {
            log.Println("参数判断ok,参数值为:")

            log.Println(time_value[])
            log.Println(beiwang_value[])

            // 定义初始时间
            const base_format = "\"2006-01-02 15:04\""

            // 转化为unix时间
            loc, _ := time.LoadLocation("Local")
            parse_time, err := time.ParseInLocation(base_format, time_value[], loc)

            unix_parse_time := parse_time.Unix()

            log.Println("Unix 时间为: ", unix_parse_time)

            if err != nil {
                fmt.Println(err)
            }

            // 需要Insert的sql
            insert_sql := fmt.Sprintf(])

            log.Println("执行的sql: ", insert_sql)

            // 执行sql
            results, err := db.Exec(insert_sql)

            if err != nil {
                log.Println("sql执行错误,错误内容为:")
                log.Println(err)
            } else {
                log.Println("执行成功,", results)
                fmt.Fprintf(w, "request ok")
            }

        } else {
            fmt.Fprintf(w, "request error")
        }
    }
}

// 发送邮件
func SendMail(body string) error {
    mailConn := map[string]string{
        "user": "from_user",
        "pass": "password",
        "host": "smtp",
        "port": "port",
    }

    port, _ := strconv.Atoi(mailConn["port"])

    m := gomail.NewMessage()
    //m.SetHeader("From" , "XD Game" + "<" mailConn["user"] + ">")
    m.SetHeader("From", "XD Game"+"<"+mailConn["user"]+">")
    m.SetHeader("To", "to_user")
    m.SetHeader("Subject", "执行计划")
    m.SetBody("text/html", body)

    d := gomail.NewDialer(mailConn["host"], port, mailConn["user"], mailConn["pass"])

    err := d.DialAndSend(m)

    return err
}

// 返回需要执行定时任务的id,返回值为Int数组
func Deal_Exec_id(db *sql.DB) []int {
    var send_id []int
    // 获取当前时间戳
    now_t := time.Now()
    // 执行查询sql
    select_datetime := fmt.Sprintf("select id from auto_backup where flag = 0 and datetime <= %d", now_t.Unix())

    // 执行sql
    select_rows, err := db.Query(select_datetime)
    log.Println(select_datetime)

    if err != nil {
        log.Println(err)
    }

    for select_rows.Next() {
        var id int

        if err := select_rows.Scan(&id); err != nil {
            log.Println(err)
        }

        //fmt.Println(id)
        // 将查询的结果追加到send_id中
        send_id = append(send_id, id)

    }
    log.Println("查询结果返回ID", send_id)

    // 将send_id数组返回
    return send_id
}

func Deal_SendMail(db *sql.DB, send_id []int) {

    var to_do string

    for id := range (send_id) {
        fmt.Println(send_id[id])

        // 根据send_id查询 messages
        select_sql := fmt.Sprintf("SELECT to_do FROM auto_backup WHERE id = '%d';", send_id[id])
        log.Println(select_sql)

        err := db.QueryRow(select_sql).Scan(&to_do)

        if err != nil {
            log.Println(err)
        }

        log.Println("发送的内容", to_do)
        SendMail(to_do)

        // 执行 update sql
        update_sql := fmt.Sprintf("UPDATE auto_backup SET flag = 1 WHERE id = '%d'", send_id[id])
        log.Println(update_sql)

        results, err := db.Exec(update_sql)

        if err != nil {
            log.Println(err)
        } else {
            log.Println(results)
        }
    }
}

func start_jobs() {

    for {
        log.Println("Auto Time jobs Start")
        send_id := Deal_Exec_id(db)
         == len(send_id) {
            log.Println("未找到相关jobs")
        } else {
            Deal_SendMail(db, send_id)
        }
        // 每隔20秒刷新一次数据库,查看是否存在新数据
        time.Sleep(time.Second * )
    }
}

// 定义*sql.DB 变量
var db *sql.DB

func main() {
    // 连接mysql
    var err error
    c := make(chan )
    db, err = sql.Open("mysql", "username:password@tcp(host)/database_name")

    // 在main退出时关闭链接
    defer db.Close()

    if err != nil {
        log.Println("Connect DB failed")
        log.Println(err)
    }

    // 开启http服务器
    http.HandleFunc("/", Httpd_beiwang)

    // 开启协程
    go func() {

        err = http.ListenAndServe("0.0.0.0:9090", nil)

        if err != nil {
            log.Fatal(err)
        }
    }()

    go start_jobs()
    <- c
}

golang打造基于mail的提醒服务的更多相关文章

  1. 翻译-使用Ratpack和Spring Boot打造高性能的JVM微服务应用

    这是我为InfoQ翻译的文章,原文地址:Build High Performance JVM Microservices with Ratpack & Spring Boot,InfoQ上的中 ...

  2. 基于 REST 的 Web 服务:基础

    代表性状态传输(Representational State Transfer,REST)在 Web 领域已经得到了广泛的接受,是基于 SOAP 和 Web 服务描述语言(Web Services D ...

  3. 新项目架构从零开始(三)------基于简单ESB的服务架构

    这几个月一直在修改架构,所以迟迟没有更新博客. 新的架构是一个基于简单esb的服务架构,主要构成是esb服务注册,wcf服务,MVC项目构成. 首先,我门来看一看解决方案, 1.Common 在Com ...

  4. 使用Ratpack和Spring Boot打造高性能的JVM微服务应用

    使用Ratpack和Spring Boot打造高性能的JVM微服务应用 这是我为InfoQ翻译的文章,原文地址:Build High Performance JVM Microservices wit ...

  5. Golang 在电商即时通讯服务建设中的实践

    马蜂窝技术原创文章,更多干货请搜索公众号:mfwtech ​即时通讯(IM)功能对于电商平台来说非常重要,特别是旅游电商. 从商品复杂性来看,一个旅游商品可能会包括用户在未来一段时间的衣.食.住.行等 ...

  6. 通过Dapr实现一个简单的基于.net的微服务电商系统

    本来想在Dpar 1.0GA时发布这篇文章,由于其他事情耽搁了放到现在.时下微服务和云原生技术如何如荼,微软也不甘示弱的和阿里一起适时推出了Dapr(https://dapr.io/),园子里关于da ...

  7. 基于thrift的微服务框架

    前一阵开源过一个基于spring-boot的rest微服务框架,今天再来一篇基于thrift的微服务加框,thrift是啥就不多了,大家自行百度或参考我之前介绍thrift的文章, thrift不仅支 ...

  8. Jquery打造的类似新浪微博@提醒功能

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. 基于TCPCopy的Dubbo服务引流工具-DubboCopy

    TCPCopy顾名思义,就是一个可以将tcp流量复制的工具(其实也可以复制UDP).有了这样一个工具,我们就可以真实的复制线上流量,然后将这些流量复制到我们的测试服务器上.这样就可以很容易模拟线上真实 ...

随机推荐

  1. Python设计模式 - UML - 定时图(Timing Diagram)

    简介 定时图也是一种交互图,用来描述对象或实体随时间变化的状态或值,及其相应的时间或期限约束.定时图应用较广,并不局限于软件工程领域. 定时图侧重与时间线相关的值或状态的改变,这些改变可能来自于收到消 ...

  2. 【相关网站 - 02】- Java 好文博客

    一.源码分析博客 还有这种操作?浅析为什么要看源码 你觉得什么才是 Java 的基础知识? 1. JDK 2. Mybatis 3. Spring 4. Sring Boot 5. Spring Cl ...

  3. Jmeter Distributed (Remote) Testing: Master Slave Configuration

    What is Distributed Testing? DistributedTestingis a kind of testing which use multiple systems to pe ...

  4. iOS内置麦克风选择方法

    模式中的 voicechat用于VoIP是由系统进行默认选择的最适合的麦克风 模式中的AVAudioSessionModeVideoRecording默认选择上麦克风,离摄像头最近的那个,主要用于VO ...

  5. zabbix学习笔记----概念----2019.03.25

    1.zabbix支持的通讯方式 1)agent:专用的代理程序,首推: 2)SNMP:  3)SSH/Telnet:  4)IPMI,通过标准的IPMI硬件接口,监控被监控对象的硬件特性. 2)zab ...

  6. 51单片机学习笔记(清翔版)(13)——LED点阵、74HC595

    如图3,点阵屏分单色和彩色,点阵屏是由许多点组成的,在一个点上,只有一颗一种颜色的灯珠,这就是单色点阵屏,彩色的在一个点上有三颗灯珠,分别是RGB三原色. 图4你可能没看出来,那么大块黄色的就是点阵屏 ...

  7. 51-迷宫(一)- java版dfs和bfs

    一天蒜头君掉进了一个迷宫里面,蒜头君想逃出去,可怜的蒜头君连迷宫是否有能逃出去的路都不知道. 看在蒜头君这么可怜的份上,就请聪明的你告诉蒜头君是否有可以逃出去的路. 输入格式 第一行输入两个整数 nn ...

  8. MYSQL后更改ROOT的密码后无法启动服务报错1067

    安装MYSQL后更改了ROOT的密码后用 net start mysql 启动时报错1067.使用以下命令:1.进入mysql安装目录的bin目录下:cd C:\Program Files\MySQL ...

  9. Oracle 有排序的分页SQL写法

    第一种: SELECT * FROM ( SELECT A.*, ROWNUM RN FROM (SELECT * FROM TABLE_NAME) A ) 第二种: SELECT * FROM ( ...

  10. [DP][NOIP2015]子串

    子串 题目描述 有两个仅包含小写英文字母的字符串 A 和 B. 现在要从字符串 A 中取出 k 个 互不重叠 的非空子串, 然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一个新的 ...