Skip to content

potato旨在快速构建一个服务端应用,提供zap等日志框架、gorm框架、http框架以及常用中间件的使用封装,可以进行极简配置就可以快速构建出完整web应用程序。

Notifications You must be signed in to change notification settings

jasonlabz/potato

Repository files navigation

potato

potato主要对go语言开发过程中常用的基础组件进行封装,包含常用加解密cryptox、错误定义errors、本地缓存gocache、gorm框架、httpclient、常用日志框架等等。

全局拥有默认的配置文件方式,也提供手动初始化配置的方式,其中redis默认会读取conf/application.yaml下的配置:

application:
  name: lg_server
  port: 8630
debug: true
kafka:
  topic: ["XXX"]
  group_id: "XXX"
  bootstrap_servers: "XXX:XX,XXX:XX,XXX:XX"
  security_protocol: "PLAINTEXT"
  sasl_mechanism: "PLAIN"
  sasl_username: "XXX"
  sasl_password: "XXX"
database:
  db_type: "mysql"
  dsn: "root:xxxxxxx!~04@tcp(1.117.xxxx.xxxx:8306)/lg_server?charset=utf8mb4&parseTime=True&loc=Local"
  #  dsn: "user=postgres password=halojeff host=127.0.0.1 port=8432 dbname=lg_server sslmode=disable TimeZone=Asia/Shanghai"
  charset: "utf-8"
  log_mode: "info"
  max_idle_conn: 100
  max_open_conn: 10
redis:
  endpoints:
    - "1.117.xxx.xxx:8379"
  password: "xxxxxx"
  index_db: 0
  MinIdleConns: 10
  max_idle_conns: 50
  max_active_conns: 10
  max_retry_times: 5
  master_name:
  sentinel_username:
  sentinel_password:
rabbitmq:
  host: 1.117.xxx.xxx
  port: 8672
  username: lucas
  password: xxxxxxxx
crypto:
  - type: aes
    key: "xxxxxxxxxxxxxx"
  - type: des
    key: "xxxxxxx"
log:
  # 是否写入文件
  write_file: true
  # true|false
  json_log: false
  # error|warn|info|debug
  log_level: debug
  # 文件配置
  log_file_conf:
    log_file_path: ./log/lg_server.log
    max_size: 10
    max_age: 28
    max_backups: 100
    compress: false

crypto

包含几种常见的加解密算法封装使用,使用默认秘钥进行初始化,可手动设置秘钥进行初始化

log

主要针对zap和slog两个日志库进行了简单的封装,支持trace_id,user_id等参数打印

日志默认配置文件: conf/application.yaml (或者conf/app.yaml) 配置文件格式:

log:
  # 是否写入文件
  write_file: true
  # true|false
  json_log: false
  # error|warn|info|debug
  log_level: debug
  # 文件配置
  log_file_conf:
    log_file_path: ./log/lg_server.log
    max_size: 10
    max_age: 28
    max_backups: 100
    compress: false

当没有配置文件时会使用默认配置初始化,初始化方式可以通过导入包路径或者显示调用初始化函数:

方式一:

import _ "github.com/jasonlabz/potato/log/zapx"
// 使用默认配置

方式二:

zapx.InitLogger(zapx.WithConfigPath("conf/application.yaml"))

将需要在日志中打印指定上下文信息时例如trace_id,user_id等等时可以通过初始化配置加入指定字段(且同时在context中缓存指定的字段进行日志记录时会从上下文中读取并打印):
zapx.InitLogger(zapx.WithConfigPath("conf/application.yaml"),zapx.WithFields("user_id", "trace_id"))

打印效果:

2024-01-07 16:08:10.147852      INFO    middleware/logger.go:68   [GIN] request   {"trace_id": "33a5fb6c15b54cc3b820c5cd1efb3b97", "remote_addr": "127.0.0.1", "method": "GET", "agent": "apifox/1.0.0 (https://www.apifox.cn)", "body": "", "client_ip": "127.0.0.1", "path": ""}
2024-01-07 16:08:10.349345      INFO    impl/user_dao_impl.go:52  [DB] [200.987ms] [rows:1] SELECT * FROM `user` WHERE `user_id` = 1 ORDER BY `user`.`user_id` LIMIT 1    {"trace_id": "33a5fb6c15b54cc3b820c5cd1efb3b97", "remote_addr": "127.0.0.1"}
2024-01-07 16:08:10.349345      INFO    middleware/logger.go:77   [GIN] response  {"trace_id": "33a5fb6c15b54cc3b820c5cd1efb3b97", "remote_addr": "127.0.0.1", "error_message": "", "body": "{\"code\":0,\"version\"
:\"v1\",\"current_time\":\"2024-01-07 16:08:10\",\"data\":[{\"user_id\":1,\"user_name\":\"武秀兰\",\"gender\":1,\"register_ip\":\"127.0.0.1\",\"register_time\":\"2023-12-23T16:51:44+08:00\"}]}", "path": "", "status_code": "200", "cost": "201ms"}
  • 使用日志zap
// 获取日志对象
logger := log.GetLogger().WithContext(ctx)
// 打印日志
logger.WithError(err).Error("get user error")

rabbitmq

rabbitmq服务简单封装了常用使用功能,支持断线重连、持续消费,支持优先级队列、延迟队列等队列参数的设置,支持rabbitmq五种常用的队列模型使用。 该库基于一个connection对应多个channel的使用理念来封装使用,一个队列/一个交换机对应一个channel。

  • 使用rabbitmq
func TestName(t *testing.T) {
    ctx := context.Background()
    
    provider := yaml.NewConfigProvider("../../conf/application.yaml")
    config.AddProviders(DefaultRMQConfName, provider)
    operator, err := rabbitmqx.NewRabbitMQOperator(&rabbitmqx.MQConfig{
        Username: config.GetString(DefaultRMQConfName, "rabbitmq.username"),
        Password: config.GetString(DefaultRMQConfName, "rabbitmq.password"),
        Host:     config.GetString(DefaultRMQConfName, "rabbitmq.host"),
        Port:     config.GetInt(DefaultRMQConfName, "rabbitmq.port"),
    })
    if err != nil {
        panic(err)
    }
    defer func(operator *rabbitmqx.RabbitMQOperator) {
        err := operator.Close()
        if err != nil {
            fmt.Println(err)
        }
    }(operator)
    logger := zapx.GetLogger().WithContext(ctx)
    pdmsg := &rabbitmqx.PushDelayBody{}
    pmsg := &rabbitmqx.PushBody{}
    msg := &rabbitmqx.ExchangePushBody{}
    msg1 := &rabbitmqx.QueuePushBody{}
    
    for i := 0; i < 1000; i++ {
        err = operator.PushDelayMessage(ctx, pdmsg.SetMsg([]byte("hello")).
            SetExchangeName("test_exchange").
            BindQueue("test_delay", "test_delay").
            BindQueue("test_delay1", "test_delay1").
            SetXMaxPriority(4, "test_delay", "test_delay1").
            SetDelayTime(25*time.Second))
        if err != nil {
            logger.Error(err.Error())
            err = nil
        }
        
        err = operator.Push(ctx, pmsg.SetMsg([]byte("hello")).
            SetExchangeName("test").
            SetPriority(1).
            BindQueue("test_queue", "test_queue").
            SetXMaxPriority(4, "test_queue"))
        if err != nil {
            logger.Error(err.Error())
            err = nil
        }
        
        err = operator.PushExchange(ctx, msg.SetMsg([]byte("hello")).
            SetExchangeName("test").
            SetPriority(1).
            BindQueue("testdddd", "testdddd").
            BindQueue("test_queue", "test_queue").
            SetXMaxPriority(4, "test_queue", "testdddd"))
        if err != nil {
            logger.Error(err.Error())
            err = nil
        }
        //err = operator.PushExchange(ctx, msg.SetMsg([]byte("hello")).OpenConfirmMode(false).SetExchangeName("test").SetPriority(1).BindQueue("testdddd", "testdddd").BindQueue("test_queue", "test_queue").SetXMaxPriority(4, "test_queue", "testdddd"))
        err = operator.PushQueue(ctx, msg1.SetMsg([]byte("hello")).
            SetQueueName("testdddd").
            SetPriority(1).
            SetXMaxPriority(4))
        if err != nil {
            logger.Error(err.Error())
            err = nil
        }
    }
    body := &rabbitmqx.ConsumeBody{}
    
    deliveries, err := operator.Consume(ctx, body.SetQueueName("test_delay").SetPrefetchCount(10))
    if err != nil {
        logger.Error(err.Error())
        return
    }
    for delivery := range deliveries {
        fmt.Println("get msg: " + delivery.MessageId + " -- " + string(delivery.Body))
        operator.Ack(ctx, delivery)
    }
}

redis

对redis五种数据类型的操作进行简单封装,支持延迟消息队列、发布订阅等功能

  • redis使用
func TestName(t *testing.T) {
    ctx := context.Background()
    
    op, err := goredis.NewRedisOperator(&goredis.Config{
        Addrs:    []string{"1.117.***.***:8379"},
        Password: "*******",
    })
    if err != nil {
        panic(err)
    }
    success, err := op.Set(ctx, "hello", "world")
    if err != nil {
        panic(err)
    }
    if success {
        fmt.Println("set success")
    }
    value, err := op.Get(ctx, "hello")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(value)
}

func TestDelayQueue(t *testing.T) {
    ctx := context.Background()
    op, err := goredis.NewRedisOperator(&goredis.Config{
        Addrs:    []string{"1.117.***.***:8379"},
        Password: "**********",
    })
    if err != nil {
        panic(err)
    }
    //result, err := op.ZRangeWithScores(ctx, "potato_delay_queue_timeout:test_delay", 0, 1715224481294)
    err = op.PushDelayMessage(ctx, "test_delay", "hello", 10*time.Second)
    if err != nil {
        panic(err)
    }
    time.Sleep(20 * time.Second)
    //fmt.Println(result)
}

About

potato旨在快速构建一个服务端应用,提供zap等日志框架、gorm框架、http框架以及常用中间件的使用封装,可以进行极简配置就可以快速构建出完整web应用程序。

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages