第一个go练习服务——编写


任务书:https://blog.csdn.net/xljiayou_/article/details/104707510

目录结构

在这里插入图片描述
本次开发项目名为first_demo,采用mvc三层架构。controller中的server.go用于创建httpserver,配置路由和处理器。
service中的service.go用于处理业务,比如查询操作,先从redis查,没有时再从mysql查。
dao中的mysql_util封装了go连接mysql的crud操作,redis_util封装了go连接redis的crud操作。
github.com目录中包含两个驱动,用于go连接redis和mysql。

开发

在开发过程中,我是从dao层开始写的,到controller层时发现底层写的方法与业务有些偏差,然后又进行了修改,在以后的开发中,最好事先理解好需求,开发时从上层开始写起。

server.go

package main

import (
	"encoding/json"
	"first_demo/dao/mysql_util"
	"first_demo/dao/redis_util"
	"fmt"
	"net/http"
	"strings"

	"first_demo/service"
)

type AddHandler struct{}
type DelHandler struct{}
type ModHandler struct{}
type QueryHandler struct{}

// 封装处理成功的信息
type succ struct {
	Ret int `json:"ret"`
	Data map[string] string `json:"data"`
}

// 封装处理失败的信息
type fail struct {
	Ret int `json:"ret"`
	Msg string `json:"msg"`
}

func (h *AddHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	fmt.Println(req.Method)
	// 如果不是POST请求,返回404
	if req.Method != "POST" {
		resp.WriteHeader(404)
		return
	}
	fmt.Println("add")

	// 对请求的json参数进行解码,存放到map中
	decoder := json.NewDecoder(req.Body)
	params := map[string] string{}
	decoder.Decode(&params)

	err := service.Add(params["key"], params["value"])

	var res []byte
	if err != nil {
		// 处理失败
		ret := -1
		msg := "add error."
		res, _ = json.Marshal(fail{ret, msg})
	}else {
		// 处理成功
		res, _ = json.Marshal(succ{1, nil})
		fmt.Println("1")
	}

	// 写入响应
	resp.Write(res)
}

func (h *DelHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	fmt.Println("del")
	if req.Method != "POST" {
		resp.WriteHeader(404)
		return
	}

	decoder := json.NewDecoder(req.Body)
	params := map[string] []string{}
	decoder.Decode(&params)

	err := service.Del(params["keys"])

	var res []byte
	if err != nil {
		res, _ = json.Marshal(fail{-1, "del error."})
	}else {
		res, _ = json.Marshal(succ{1, nil})
	}

	resp.Write(res)
}

func (h *ModHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	fmt.Println("mod")
	if req.Method != "POST" {
		resp.WriteHeader(404)
		return
	}

	decoder := json.NewDecoder(req.Body)
	params := map[string] string{}
	decoder.Decode(&params)

	err := service.Mod(params["key"], params["value"])

	res := []byte{}
	if err != nil {
		res, _ = json.Marshal(fail{-1, "mod error."})
	}else {
		res, _ = json.Marshal(succ{1, nil})
	}

	resp.Write(res)
}

func (h *QueryHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	fmt.Println("query")
	if req.Method != "POST" {
		resp.WriteHeader(404)
		return
	}

	// 将输入的json数据,解码存放到map中
	decoder := json.NewDecoder(req.Body)
	m := map[string] []string{}
	decoder.Decode(&m)

	kvs, err := service.Query(m["keys"])

	res := []byte{}
	if err != nil {
		res, _ = json.Marshal(fail{-1, "query error."})
	}else {
		res, _ = json.Marshal(succ{1, kvs})
	}

	resp.Write(res)
}

// 将数组字符串转换成切片
func strToSlice(str string) []string {
	str = strings.ReplaceAll(str[1:len(str)-1], "\"", "")
	return strings.Split(str,",")
}

func main() {
	// 建立redis连接和mysql连接
	redis_util.StartRedis()
	mysql_util.StartMysql()

	// 建立路由表
	http.Handle("/add", &AddHandler{})
	http.Handle("/del", &DelHandler{})
	http.Handle("/mod", &ModHandler{})
	http.Handle("/query", &QueryHandler{})

	// 监听本地端口
	http.ListenAndServe(":8000", nil)
}

service.go

package service

import (
	"first_demo/dao/mysql_util"
	"first_demo/dao/redis_util"
)

func Add(key, value string) error {
	return mysql_util.AddByKeyValue(key, value)
}

func Del(keys []string) error {
	for _, key := range(keys) {
		// 同时在redis 和 mysql中删除
		redis_util.DelByKey(key)
		err := mysql_util.DelByKey(key)
		if err != nil {
			return err
		}
	}
	return nil
}

func Mod(key, value string) error {
	// 在mysql中更新
	err := mysql_util.ModByKeyValue(key, value)
	if err != nil {
		return err
	}
	// 在redis中删除
	redis_util.DelByKey(key)
	return nil
}

func Query(keys []string) (map[string]string, error) {
	// 存储查询到的结果
	kvs := map[string] string{}

	for _, key := range(keys) {
		// 对每个key,现在redis中进行查找
		value, err := redis_util.QueryByKey(key)
		if err == nil {
			kvs[key] = value
			continue
		}

		// 如果redis里中没有,在mysql中查找
		value, err = mysql_util.QueryByKey(key)
		if err != nil {
			return nil, err
		}

		// 如果找到,将数据写入到redis中
		kvs[key] = value
		err = redis_util.AddKeyValue(key, value)
		if err != nil {
			return nil, err
		}
	}
	return kvs, nil
}

mysql_util.go

package mysql_util

import (
	"database/sql"
	"errors"
	"fmt"

	_ "github.com/go-sql-driver/mysql"
)

var db *sql.DB

func StartMysql() {
	var err error
	db, err = sql.Open("mysql", "root:Xuelei123@tcp(127.0.0.1:3306)/first_demo?charset=utf8")
	if err != nil {
		fmt.Println("connect mysql error!")
		return
	}
}

func QueryByKey(key string) (string, error) {
	var v string
	stmt, _ := db.Prepare("select `value` from key_value where `key`=?")
	row := stmt.QueryRow(key)
	err := row.Scan(&v)
	return v, err
}

func DelByKey(key string) error {
	stmt, _ := db.Prepare("delete from key_value where `key` = ?")
	_, err := stmt.Exec(key)
	return err
}

func ModByKeyValue(key, value string) error {
	result, err := db.Exec("update key_value set `value`=? where `key`=?", value, key)
	if err != nil {
		return err
	}
	if i, _ :=result.RowsAffected(); i == 0 {
		return errors.New("mod error.")
	}
	return nil
}

func AddByKeyValue(key, value string) error {
	res, err := db.Exec("insert into key_value values(?, ?)", key, value)
	if err != nil {
		return err
	}
	if i, _ := res.RowsAffected(); i == 0 {
		return errors.New("insert error.")
	}
	return nil
}

redis_util.go

package redis_util

import (
	_ "errors"
	"fmt"
	"github.com/garyburd/redigo/redis"
)

// 设置存储时间
const LIVETIME string = "300"

var conn redis.Conn

func StartRedis() {
	var err error
	conn, err = redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("connect error.")
		return
	}
}

func QueryByKey(key string) (string, error) {
	value, err := redis.String(conn.Do("Get", key))
	return value, err
}

func DelByKey(key string) error {
	_, err := conn.Do("DEL", key)
	return err
}

func ModByKeyValue(key, value string) error {
	_, err := redis.String(conn.Do("SET", key, value, "EX", LIVETIME))
	return err
}

func AddKeyValue(key, value string) error {
	_, err := conn.Do("SET", key, value, "EX", LIVETIME)
	return err
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dlian丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值