【Golang】关于Golang中一些优秀的类库
一、CLI 命令(spf13/cobra)
GitHub地址:https://github.com/spf13/cobra

Cobra既是一个创建强大的现代CLI应用程序的库,也是一个生成应用程序和命令的程序。可以使用这个库来管理命令应用程序,执行runner应用程序,初始化配置,病启动Reast API。
基于Cobra的应用的目录结构:
├── app │ ├── main.go │ ├── cmd │ └────── root.go │ └────── helper.go │ └────── version.go
在 app/main.go 中:
package main
import (
"app/cmd"
)
func main() {
cmd.Execute()
}
在 app/cmd/root.go 中:
package cmd
import (
"errors"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "git",
Short: "Git is a distributed version control system.",
Long: `Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.`,
Run: func(cmd *cobra.Command, args []string) {
Error(cmd, args, errors.New("unrecognized command"))
},
}
func Execute() {
rootCmd.Execute()
}
在 app/cmd/helper.go 中:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"os"
"os/exec"
)
func ExecuteCommand(name string, subname string, args ...string) (string, error) {
args = append([]string{subname}, args...)
cmd := exec.Command(name, args...)
bytes, err := cmd.CombinedOutput()
return string(bytes), err
}
func Error(cmd *cobra.Command, args []string, err error) {
fmt.Fprintf(os.Stderr, "execute %s args:%v error:%v\n", cmd.Name(), args, err)
os.Exit(1)
}
在 app/cmd/version.go 中:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"os"
)
var versionCmd = &cobra.Command{
Use: "version",
Short: "version subcommand show git version info.",
Run: func(cmd *cobra.Command, args []string) {
output, err := ExecuteCommand("git", "version", args...)
if err != nil {
Error(cmd, args, err)
}
fmt.Fprint(os.Stdout, output)
},
}
func init() {
rootCmd.AddCommand(versionCmd)
}
开始运行
PS G:\go-demo\test11> go run main.go --help Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Usage: git [flags] git [command] Available Commands: completion Generate the autocompletion script for the specified shell help Help about any command version version subcommand show git version info. Flags: -h, --help help for git Use "git [command] --help" for more information about a command.
二、ORM:Gorm
GitHub地址:https://github.com/go-gorm/gorm/推荐理由:代码优雅,场景非常丰富,满足我们的SQL场景需求,比如:
- 全功能ORM
- 关联(拥有一个、拥有多个、属于、多对多、多态、单表继承)
- Create,Save,Update,Delete,Find 中钩子方法
- 支持 Preload、Joins 的预加载
- 事务,嵌套事务,Save Point,Rollback To to Saved Point
- Context、预编译模式、DryRun 模式
- 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD
- SQL 构建器,Upsert,锁,Optimizer/Index/Comment Hint,命名参数,子查询
- 复合主键,索引,约束
- 自动迁移
- 自定义 Logger
- 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
- 每个特性都经过了测试的重重考验
三、SQL(jmoiron/sqlx)
GitHub地址:https://github.com/jmoiron/sqlx
是sqlx的一个库,在Go的标准database/sql库上提供了一组扩展。
示例:
place := Place{}
rows, err := db.Queryx("SELECT * FROM place")
for rows.Next() {
err := rows.StructScan(&place)
if err != nil {
log.Fatalln(err)
}
fmt.Printf("%#v\n", place)
}
四、配置管理:viper
GitHub地址:https://github.com/spf13/viper
- 支持JSON/TOML/YAML/HC:/en:L/envfile/Java properties等多种格式的配置文件;
- 可以设置监听配置文件的修改,修改时自动加载新的配置;
- 从环境变量、命令行选项和io。Reader中读取配置;
- 从远程配置系统中读取和监听修改,如etcd/Consu;
- 代码逻辑中显示设置键值
五、日志管理:zap
GitHub地址::GitHub - uber-go/zap: Blazing fast, structured, leveled logging in Go.
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", url)
六、消息队列 asynq
Github地址: GitHub - hibiken/asynq: Simple, reliable, and efficient distributed task queue in Go
可靠、简单、高效的分布式任务队列。
七、消息传递 NSQ
GitHub地址:https://github.com/nsqio/go-nsq
NSQ 拓扑
NSQ 组件:
- nsqlookupd (守护进程管理拓扑 / 路由)
- nsqd(守护进程管理接收、排队和传递消息)
- nsqadmin(nsq 的默认 Web UI)
docker-compose 示例:(nsqlookupd, nsqd, nsqadmin)
version: '3' services: nsqlookupd: image: nsqio/nsq command: /nsqlookupd ports: - "4160:4160" - "4161:4161" nsqd: image: nsqio/nsq command: /nsqd --lookupd-tcp-address=nsqlookupd:4160 depends_on: - nsqlookupd ports: - "4150:4150" - "4151:4151" nsqadmin: image: nsqio/nsq command: /nsqadmin --lookupd-http-address=nsqlookupd:4161 depends_on: - nsqlookupd ports: - "4171:4171"
执行:
运行 docker: $ docker-compose up -d 或者,如果使用名称 (docker-compose-nsq.yml): $ docker-compose -f docker-compose-nsq.yml up -d 检查容器 docker: $ docker-compose ps 查看日志: $ docker-compose logs 检查 nsq Web UI(假设端口为 32770): $ curl http://127.0.0.1:32770/ping
目录结构:
├── consume
│ └── consume.go
└── publish
└── publish.go
consume.go:
package main
import (
"github.com/nsqio/go-nsq"
"log"
"sync"
)
func main() {
wg := &sync.WaitGroup{}
wg.Add(1)
decodeConfig := nsq.NewConfig()
c, err := nsq.NewConsumer("My_NSQ_Topic", "My_NSQ_Channel", decodeConfig)
if err != nil {
log.Panic("Could not create consumer")
}
c.AddHandler(nsq.HandlerFunc(func(message *nsq.Message) error {
log.Println("NSQ message received:")
log.Println(string(message.Body))
return nil
}))
err = c.ConnectToNSQD("127.0.0.1:4150")
if err != nil {
log.Panic("Could not connect")
}
log.Println("Awaiting messages from NSQ topic \"My NSQ Topic\"...")
wg.Wait()
}
运行 consume.go:
$ go run consume/consume.go
publish.go:
package main
import (
"log"
"github.com/nsqio/go-nsq"
)
func main() {
config := nsq.NewConfig()
p, err := nsq.NewProducer("127.0.0.1:4150", config)
if err != nil {
log.Panic(err)
}
err = p.Publish("My_NSQ_Topic", []byte("sample NSQ message"))
if err != nil {
log.Panic(err)
}
}
运行 publish.go:
$ go run publish/publish.go
八、JSON校验库
-
golang json 校验库
GitHub地址:https://github.com/go-playground/validator
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
// User contains user information
type User struct {
FirstName string `validate:"required"`
LastName string `validate:"required"`
Age uint8 `validate:"gte=0,lte=130"`
Email string `validate:"required,email"`
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
}
// Address houses a users address information
type Address struct {
Street string `validate:"required"`
City string `validate:"required"`
Planet string `validate:"required"`
Phone string `validate:"required"`
}
// use a single instance of Validate, it caches struct info
var validate *validator.Validate
func main() {
validate = validator.New()
validateStruct()
validateVariable()
}
func validateStruct() {
address := &Address{
Street: "Eavesdown Docks",
Planet: "Persphone",
Phone: "none",
}
user := &User{
FirstName: "Badger",
LastName: "Smith",
Age: 135,
Email: "Badger.Smith@gmail.com",
FavouriteColor: "#000-",
Addresses: []*Address{address},
}
// returns nil or ValidationErrors ( []FieldError )
err := validate.Struct(user)
if err != nil {
// this check is only needed when your code could produce
// an invalid value for validation such as interface with nil
// value most including myself do not usually have code like this.
if _, ok := err.(*validator.InvalidValidationError); ok {
fmt.Println(err)
return
}
for _, err := range err.(validator.ValidationErrors) {
fmt.Println(err.Namespace())
fmt.Println(err.Field())
fmt.Println(err.StructNamespace())
fmt.Println(err.StructField())
fmt.Println(err.Tag())
fmt.Println(err.ActualTag())
fmt.Println(err.Kind())
fmt.Println(err.Type())
fmt.Println(err.Value())
fmt.Println(err.Param())
fmt.Println()
}
// from here you can create your own error messages in whatever language you wish
return
}
// save user to database
}
func validateVariable() {
myEmail := "joeybloggs.gmail.com"
errs := validate.Var(myEmail, "required,email")
if errs != nil {
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
return
}
// email ok, move on
}
九、map to structure
-
golang map to structure 的库
GitHub地址:https://github.com/mitchellh/mapstructure
package main
import (
"encoding/json"
"fmt"
"github.com/mitchellh/mapstructure"
)
type Demo struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
var value = make(map[string]Demo)
value["1"] = Demo{
ID: 1,
Name: "name-1",
}
valueData, err := json.Marshal(value)
if err != nil {
panic(err)
}
var newValue interface{}
if err = json.Unmarshal(valueData, &newValue); err != nil {
panic(err)
}
// 反序列化之后只能强转为map[string]interface{}
for _, v := range newValue.(map[string]interface{}) {
/*
此时可以使用mapstructure.Decode方法编码,该方法使用的是反射的机制;
也可以对v进行序列化,然后反序列化给demo变量;
*/
var demo Demo
if err = mapstructure.Decode(v, &demo); err != nil {
panic(err)
}
fmt.Println(demo)
}
}
- 作者:踏雪无痕
- 出处:http://www.cnblogs.com/chenpingzhao/
- 本文版权归作者和博客园共有,如需转载,请联系 pingzhao1990#163.com

浙公网安备 33010602011771号