【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