IXHONG 阅读(54) 评论(0)

www.toutiao.im

 

mygo
  |-bin
  |-pkg
  |-src
    |-go.web.red
      |-comm_log
        comm_log.go
      |-handler
        red_handler.go
        red_parameter_validate.go
        user_handler.go
      |-module
        db_init.go
        user_module.go
      |-system_cfg
        system_cfg_process.go
      |-system_notify
        system_notify_process.go
      conf.ini
      web.go
 

 comm_log.go

 

 

package comm_log

import (
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "time"
)

var default_log *Zlog

type Zlog struct {
    zap_log *zap.SugaredLogger
    curr_log_level zap.AtomicLevel
}

func Init(program_name, log_level_str, log_path string) *Zlog {
    encoder_cfg := zapcore.EncoderConfig{
        TimeKey:        "T",
        LevelKey:       "L",
        NameKey:        "N",
        CallerKey:      "C",
        MessageKey:     "M",
        StacktraceKey:  "S",
        LineEnding:     zapcore.DefaultLineEnding,
        EncodeLevel:    zapcore.CapitalLevelEncoder,
        EncodeTime:     time_encoder,
        EncodeDuration: zapcore.StringDurationEncoder,
        EncodeCaller:   zapcore.ShortCallerEncoder,
    }

    log_level := zap.NewAtomicLevel()
    log_level.UnmarshalText([]byte(log_level_str))

    custom_cfg := zap.Config{
        Level:            log_level,
        Development:      true,
        Encoding:         "console",
        EncoderConfig:    encoder_cfg,
        OutputPaths:      []string{log_path},
        ErrorOutputPaths: []string{"stderr"},
    }

    logger, _ := custom_cfg.Build()
    new_logger := logger.Named(program_name)
    sugar := new_logger.Sugar()

    default_log = &Zlog{
        zap_log: sugar,
        curr_log_level : log_level,
    }

    return default_log
}

func Sync()  {
    default_log.zap_log.Sync()
}

func Debug(msg string, keysAndValues ...interface{}) {
    default_log.zap_log.Debugw(msg, keysAndValues...)
}

func Info(msg string, keysAndValues ...interface{})  {
    default_log.zap_log.Infow(msg, keysAndValues...)
}

func Warn(msg string, keysAndValues ...interface{}) {
    default_log.zap_log.Warnw(msg, keysAndValues...)
}

func Error(msg string, keysAndValues ...interface{}) {
    default_log.zap_log.Errorw(msg, keysAndValues...)
}

func Set_log_level(log_level string) {
    default_log.curr_log_level.UnmarshalText([]byte(log_level))
}

func Get_log_level() string {
    return default_log.curr_log_level.String()
}

func time_encoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
    enc.AppendString("[" + t.Format("2006-01-02 15:04:05") + "]")
}

 red_handler.go

 

 

package handler

import "github.com/labstack/echo"

// http response status_code
const(
	SUCCESS 		= "0"
	DBERROR 		= "1"
	SERVERERROR 	= "2"
	REQUESTERROR 	= "3"
)

const DATAFORMAT = "2006-01-02 15:04:05"

type (
	Base_req_entity struct {
		TrackId		string	`validate:"lte_len=20"`
	}

	Base_res_entity struct {
		Status_code		string `json:"status_code"`
	}

)
type Red_handle interface {
	Access_path() string
	Support_method() []string
	Handler(cont echo.Context) error
}

type Red_com_handle struct {
	Path          string
	Handler_works map[string]func(echo.Context)(error)
}

func (this *Red_com_handle)Access_path() string {
	return this.Path
}

func (this *Red_com_handle)Support_method() []string {
	sup_methods := []string{}
	for method, _ := range this.Handler_works {
		sup_methods = append(sup_methods, method)
	}
	return sup_methods
}

func (this *Red_com_handle)Handler(cont echo.Context) (ret error) {
	return 	this.Handler_works[cont.Request().Method](cont)
}

 red_parameter_validate.go

 

 

package handler

import (
    "github.com/go-playground/validator"
    "reflect"
    "strconv"
    "unicode/utf8"
    "fmt"
)

var Validate *validator.Validate

func init()  {
    Validate = validator.New()

    Validate.RegisterValidation("lte_len", LteLengthOf)
}

func LteLengthOf(fl validator.FieldLevel) bool {

    field := fl.Field()
    param := fl.Param()

    switch field.Kind() {

    case reflect.String:
        p, _ := strconv.ParseInt(param, 0, 64)

        return int64(utf8.RuneCountInString(field.String())) <= p
    }

    panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}

 user_handler.go

 

 

package handler

import (
	"github.com/labstack/echo"
	"net/http"
	"fmt"
	"go.web.red/module"
)

var User_default *User_entity

func init() {
	User_default = &User_entity{
		module: new(module.User),
		 Red_com_handle: Red_com_handle{
			Path: "user",
			Handler_works: make(map[string]func(echo.Context)(error)),
		},
	}

	User_default.Handler_works[echo.GET] = User_default.get
	User_default.Handler_works[echo.POST] = User_default.post
	User_default.Handler_works[echo.DELETE] = User_default.delete
	User_default.Handler_works[echo.PUT] = User_default.put
}

type User_entity struct {
	Red_com_handle
	module *module.User
}

type (
	User_param struct {
		Name     string			`json:"name" validate:"required,lte_len=50"`
		Age      int                    `json:"age"`
		Address  string                 `json:"address"`
		Status   int			`json:"status"`
		Created  string			`json:"create_time"`
		Modified string			`json:"update_time"`
	}

	User_param_all struct {
		User_param
		Id		int		`json:"id" validate:"required,lte_len=10"`
	}

	User_get_req struct {
		Base_req_entity
		Id		int
		Status		int
	}

	User_get_res struct {
		Base_res_entity
		Users []User_param_all `json:"users"`
	}

	User_post_req struct {
		Base_req_entity
		User_param
	}

	User_put_req struct {
		Base_req_entity
		User_param_all
	}

	User_delete_req struct {
		Base_req_entity
		Id	int	`validate:"required"`
	}
)

func (entity *User_entity) get(cont echo.Context) error {
	req := User_get_req{
		Base_req_entity: Base_req_entity{
			TrackId: cont.QueryParam("trackId"),
		},
		Id: cont.QueryParam("id"),
		Status: cont.QueryParam("status"),
	}

	res := User_get_res{}

	if err := Validate.Struct(&req); err != nil {
		res.Status_code = REQUESTERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	queryParams := map[string]interface{}{}

	queryParams["status"] = req.Status

	users, err := entity.module.Query(req.TrackId, queryParams)

	if err != nil {
		res.Status_code = DBERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	if len(users) == 0 {
		res.Users = []User_param_all{}
	} else {
		for _, user := range users {
			res.Users = append(res.Users, User_param_all{
				User_param: User_param{
					Name: user.Name,
					Age: user.Age,
					Address: user.Address,
					Status: user.Status,
					Modified: user.Modified.Format(DATAFORMAT),
					Created: user.Created.Format(DATAFORMAT),
				},
				Id: user.Id,
			})
		}
	}

	res.Status_code = SUCCESS

	return cont.JSON(http.StatusOK, res)
}

func (entity *User_entity) post(cont echo.Context) error {
	req := new(User_post_req)
	res := new(Base_res_entity)

	if err := cont.Bind(req); err != nil {
		fmt.Println(err.Error())
		res.Status_code = REQUESTERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	req.TrackId = cont.QueryParam("trackId")

	if err := Validate.Struct(req); err != nil {
		fmt.Println(err.Error())
		res.Status_code = REQUESTERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	user := module.User{
		Name: req.Name,
		Age: req.Age,
		Address: req.Address,
		Status: req.Status,
	}

	err := entity.module.Save(req.TrackId, user)

	if err != nil {
		fmt.Println(err.Error())
		res.Status_code = DBERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	res.Status_code = SUCCESS
	return cont.JSON(http.StatusOK, res)
}

func (entity *User_entity) delete(cont echo.Context) error {
	req := User_delete_req{
		Base_req_entity: Base_req_entity{
			TrackId: cont.QueryParam("trackId"),
		},
		Id: cont.QueryParam("id"),
	}

	res := Base_res_entity{}


	if err := Validate.Struct(&req); err != nil {
		res.Status_code = REQUESTERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	err := entity.module.Delete(req.TrackId, req.Id)

	if err != nil {
		res.Status_code = DBERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	res.Status_code = SUCCESS
	return cont.JSON(http.StatusOK, res)
}

func (entity *User_entity) put(cont echo.Context) error {
	req := new(User_put_req)
	res := new(Base_res_entity)

	if err := cont.Bind(req); err != nil {
		fmt.Println(err.Error())
		res.Status_code = REQUESTERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	req.TrackId = cont.QueryParam("trackId")

	if err := Validate.Struct(req); err != nil {
		fmt.Println(err.Error())
		res.Status_code = REQUESTERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	user := module.User{
		Id: req.Id,
		Name: req.Name,
		Age: req.Age,
		Address: req.Address,
		Status: req.Status,
	}

	err := entity.module.Update(req.TrackId, user)

	if err != nil {
		fmt.Println(err.Error())
		res.Status_code = DBERROR
		return cont.JSON(http.StatusBadRequest, res)
	}

	res.Status_code = SUCCESS
	return cont.JSON(http.StatusOK, res)
}

 db_init.go

 

 

package module

import (
	"github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
	"time"
	"fmt"
	"errors"
	"go.web.red/system_cfg"
)

var Db_instance *gorm.DB

var (
	SAVE_AFFECTED_ZERO_ERROR = errors.New("save affected row 0")
	UPDATE_AFFECTED_ZERO_ERROR = errors.New("update affected row 0")
	DELETE_AFFECTED_ZERO_ERROR = errors.New("delete affected row 0")
)

const (
	STATUS_NORMAL 	= 1
	STATUS_SUSPEND 	= 2
	STATUS_ABANDON 	= 3
)

func init() {
	ip,_ := system_cfg.System_cfg.GetValue("mysql", "ip")
	port,_ := system_cfg.System_cfg.GetValue("mysql", "port")
	user,_ := system_cfg.System_cfg.GetValue("mysql", "user")
	pwd,_ := system_cfg.System_cfg.GetValue("mysql", "pwd")
	db,_ := system_cfg.System_cfg.GetValue("mysql", "db")

	dsn := mysql.Config{
		Addr: ip+":"+port,
		User: user,
		Passwd: pwd,
		Net: "tcp",
		DBName: db,
		Params: map[string]string{"charset": "utf8", "parseTime": "True", "loc": "Local"},
		Timeout: time.Duration(5 * time.Second),
	}

	db, err := gorm.Open("mysql", dsn.FormatDSN())

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

	Db_instance = db
}

 user_module.go

 

 

package module

import (
	"time"
)

type User struct {
	Id          int `grom:"primary_key"`
	Name        string `grom:"not null;unique"`
	Age         int `grom:"not null"`
	Address     string
	Status      int	`grom:"not null"`
	Created     time.Time	`gorm:"column:created"`
	Modified    time.Time	`gorm:"column:modified"`
}

func (user *User) Save(trackId string, user User) error {
	res := Db_instance.Create(&user)

	if res.Error != nil {
		return res.Error
	}

	if res.RowsAffected == 0 {
		return SAVE_AFFECTED_ZERO_ERROR
	}

	return nil
}
func (user *User) Update(trackId string, user User) error {
	record := User{}
	updates := map[string]interface{}{
		"name": user.Name,
		"age": user.Age,
		"address": user.Address,
		"status": user.Status,
	}

	res := Db_instance.Model(&record).Where("id=?", user.Id).Update(updates)

	if res.Error != nil {
		return res.Error
	}

	if res.RowsAffected == 0 {
		return UPDATE_AFFECTED_ZERO_ERROR
	}

	return nil
}
func (user *User) Delete(trackId string, id int) error {
	record := User{}

	res := Db_instance.Where("id=?", id).Delete(record)

	if res.Error != nil {
		return res.Error
	}

	if res.RowsAffected == 0 {
		return DELETE_AFFECTED_ZERO_ERROR
	}

	return nil
}

func (user *User) Query(trackId string, queryParams map[string]interface{}) ([]User, error) {
	records := [] User{}

	res := Db_instance.Where(queryParams).Find(&records)

	if res.Error != nil {
		return []User{}, res.Error
	}

	return records, nil
}

 system_cfg_process.go

 

 

package system_cfg

import (
	"github.com/Unknwon/goconfig"
	"log"
	"fmt"
	"os"
	"path/filepath"
)

var System_cfg *goconfig.ConfigFile

func init()  {
	fileAbsPath := filepath.Dir(os.Args[0])
	fmt.Printf("current path = %s\n", fileAbsPath)
	cfg, err := goconfig.LoadConfigFile(fileAbsPath + "/conf.ini")
	if err != nil{
		log.Fatalf("load config conf.ini error = %s", err)
	}
	System_cfg = cfg
}

 system_notify_process.go

 

 

package system_notify

import (
	"strings"
	"github.com/go-gomail/gomail"
	"html/template"
	"bytes"
	"os_adv_engine/system_cfg"
	"strconv"
	"fmt"
	"encoding/json"
	"net/http"
	"io/ioutil"
)

type CsNotify interface {
	SendNotify(string, string) bool
}

var notifyList []CsNotify

func init() {
	smtp_s_str, _ := system_cfg.System_cfg.GetValue("email_notify", "smtp_server")
	smtp_p_str, _ := system_cfg.System_cfg.GetValue("email_notify", "smtp_port")
	sender_str, _ := system_cfg.System_cfg.GetValue("email_notify", "sender")
	passwd_str, _ := system_cfg.System_cfg.GetValue("email_notify", "passwd")

	receivers := []string{}
	receiversStr, _ := system_cfg.System_cfg.GetValue("email_notify", "receivers")
	for _, receiverStr := range strings.Split(receiversStr, ";") {
		receivers = append(receivers, strings.TrimSpace(receiverStr))
	}

	smtp_p_int, _ := strconv.Atoi(smtp_p_str)

	en := &EmailNotify{
		smtp_s: smtp_s_str,
		smtp_p: smtp_p_int,
		fromer: sender_str,
		toers: receivers,
		ccers: []string{},
		e_user: strings.Split(sender_str, "@")[0],
		e_passwd: passwd_str,
	}
	notifyList = append(notifyList, en)

	ln := &LanxinNotify{
		app_id:"",
		app_secret:"",
		host:"",
		tousers:"",
	}
	notifyList = append(notifyList, ln)
}

func Notify(title string, content string) {
	for _,value := range notifyList {
		value.SendNotify(title, content)
	}
}

type (
	EmailNotify struct {
		smtp_s string
		smtp_p int
		fromer string
		toers  []string
		ccers  []string
		e_user string
		e_passwd string
	}

	LanxinNotify struct {
		app_id string
		app_secret string
		host string
		tousers string
	}
)

func (ln * LanxinNotify)SendNotify(title string, content string) bool {

	return true
}

func (en *EmailNotify)SendNotify(title string, content string) bool {
	msg := gomail.NewMessage()
	msg.SetHeader("From", en.fromer)
	msg.SetHeader("To", en.toers...)
	msg.SetHeader("Subject", title)

	msg.SetBody("text/html", en.renderNotify(content))

	mailer := gomail.NewDialer(en.smtp_s, en.smtp_p, en.e_user, en.e_passwd)
	if err := mailer.DialAndSend(msg); err != nil {
		panic(err)
	}
	return true

}

func (en *EmailNotify) renderNotify(content string) string {
	tplStr := `<html>
<body>
 {{.}}
</table>
</body>
</html>`

	outBuf := &bytes.Buffer{}
	tpl := template.New("email notify template")
	tpl, _ = tpl.Parse(tplStr)
	tpl.Execute(outBuf, content)

	return outBuf.String()
}

func httpGet(url string) string{
	resp, err := http.Get(url)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	return fmt.Sprintf(string(body))
}

 web.go

 

 

package main

import (
	"github.com/labstack/echo"
	"github.com/go-playground/validator"
	"strings"
	"log"
	"go.web.red/red_handler"
)

type (
	handle_entity struct {
		h_func_set []string
		handler func(echo.Context)(error)
	}

	handle_bundle struct {
		root_url string
		api_ver string
		h_path_set map[string]handle_entity
		validate *validator.Validate
	}
)

var Default_hb *handle_bundle

func init() {
	Default_hb = &handle_bundle{
		root_url: "/ads/api",
		api_ver: "v1",
		h_path_set: make(map[string]handle_entity),
	}

	var handlers []handler.Red_handle
	handlers = append(handlers,
		)
}

func main() {
	es := echo.New()

	for path, entity := range Default_hb.h_path_set {
		paths := []string{Default_hb.root_url, Default_hb.api_ver, path}
		full_path := strings.Join(paths, "/")
		es.Match(entity.h_func_set, full_path, entity.handler)
	}

	log.Fatalln(es.Start(":8888"))
}

 conf.ini

 

[email_notify]
smtp_server = smtp.qq.com
smtp_port = 25
sender = xx@qq.com
passwd =
receivers = yy@qq.com;zz@qq.com

[mysql]
ip =
port =
user =
pwd =
db =

 

 

代码见 http://git.toutiao.im