32
Golang常用的中间件使用总结
source link: https://www.tuicool.com/articles/ee2iIbJ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
从接触go到现在大概接近一年时间了吧,主要用它来开发GPU集群管理的client端以及一些小的工具,例如:服务端mock测试、ID生成器等,给我的感觉就是高性能、低消耗、够轻量,所以在目前容器化、微服务化火热的今天,其扮演着重要角色,如:docker、k8s、istio、prometheus等都是基于go开发,国内很多一线大厂都开始主推go作为他们的服务端开发语言,如:头条、B站、流利说等,其生态也在不断的发展,今天主要将我之前用到过的常用组件和中间件总结分享一下,便于后续快速搭建开发环境。
- Gin(github.com/gin-gonic/gin):web开发框架,适合api接口、微服务开发,相较于其他框架(iris、beego)更轻量级和更好的性能。其路由功能很强大提供分组功能,非常适合做api开发,具体demo如下:
route := gin.Default() // get method route.GET("/testGet", func(c *gin.Context) { name := c.Query("name") c.String(http.StatusOK, "hello " + name) }) // post method route.POST("/testPost", func(c *gin.Context) { param := Param{} if err := c.BindJSON(¶m); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": 1, "msg" : "error", }) return } s := fmt.Sprintf("name:%s, age:%s", param.Name, param.Age) c.JSON(http.StatusOK, gin.H{ "code": 0, "msg": s, }) }) // route group v1 := route.Group("/v1") { v1.POST("/getInfo", func(c *gin.Context) { name := c.PostForm("name") c.JSON(http.StatusOK, gin.H{"msg": "hello " + name}) }) } v2 := route.Group("/v2") { v2.POST("/getInfo", func(c *gin.Context) { name := c.PostForm("name") age := c.PostForm("age") s := fmt.Sprintf("hello %s, i'm %s", name, age) c.JSON(http.StatusOK, gin.H{"msg": s}) }) } route.Run(":8080")
- Mysql(github.com/go-sql-driver/mysql):mysql第三方开源库的实现,提供原生sql功能,喜欢框架的童鞋可以去看看国人写的Gorm,挺不错的一个orm框架(我还是比较习惯写原生sql ^ _ ^ )。
// init dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:3306)/iray_proxy?charset=utf8mb4", "root", "root123", "127.0.0.1") conn, err := sql.Open("mysql", dataSourceName) if err != nil { panic(err) } db.SetMaxOpenConns(30) db.SetMaxIdleConns(10) db.SetConnMaxLifetime(10 * time.Minute) db.Ping() // select rows, err1 := conn.Query("select name, age from t_user where age > ? and age < ?", 20, 30) defer rows.Close() if err1 != nil { panic(err1) } result := make([]map[string] interface{}, 0) for rows.Next() { var name string var age int err1 = rows.Scan(&name, &age) if err1 != nil { log.Printf("row scan error: %s", err1.Error()) } else { record := make(map[string] interface{}, 1) record["name"] = name record["age"] = age result = append(result, record) } } // insert stmt, err2 := conn.Prepare("insert into t_user (name, age) values (?, ?)") if err2 != nil { panic(err2) } rs, err3 := stmt.Exec("jack", 25) if err3 != nil { log.Printf("insert row error: %s", err3.Error()) } else { rowCount, _ := rs.RowsAffected() log.Printf("insert row count: %s", strconv.FormatInt(rowCount, 10)) } // update stm1, err4 := conn.Prepare("update t_user set age = ? where name = ?") if err4 != nil { panic(err4) } rs1, err5 := stm1.Exec(30, "jack") if err5 != nil { log.Printf("update row error: %s", err5.Error()) } else { rowCount, _ := rs1.RowsAffected() log.Printf("update row count: %s", strconv.FormatInt(rowCount, 10)) } // delete rs2, err6 := conn.Exec("delete from t_user where name = ?", "jack") if err6 != nil { panic(err6) } rowCount, _ := rs2.RowsAffected() log.Printf("delete row count: %s", strconv.FormatInt(rowCount, 10))
- Redis(github.com/go-redis/redis):redis客户端的第三方开源库,比较出名两个中的一个,还有个是redigo(github.com/garyburd/redigo/redis),喜欢谁就用谁,我使用的是go-redis,具体操作如下:
// Init redisClient := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", Password: "123456", DB: 1, PoolSize: 50, }) // Hash err := redisClient.HSet("hash_key", "name", "jason statham").Err() if err != nil { log.Printf("hset error: %s", err) } resp := redisClient.HGet("hash_key", "name").Val() log.Printf("hget result: %s", resp) // List err = redisClient.RPush("list_key", "adam levin").Err() if err != nil { log.Printf("right push error: %s", err) } rs, err := redisClient.LPop("list_key").Result() log.Printf("left pop : %s", rs) // Set err = redisClient.SAdd("set_key", "harry kane").Err() if err != nil { log.Printf("add error: %s", err) } resultSet, err := redisClient.SMembers("set_key").Result() if err != nil { log.Printf("smembers error : %s", err) } else { for i, item := range resultSet { log.Printf("smembers item[%s] : %s", strconv.Itoa(i), item) } } // SortSet item := redis.Z{Score: float64(time.Now().Unix()), Member: "jet brains"} count, err := redisClient.ZAdd("sortset_key", item).Result() if err != nil { log.Printf("zadd error : %s", err) } else { log.Printf("zadd count : %s", strconv.FormatInt(count, 10)) } results, err := redisClient.ZRangeByScore("sortset_key", redis.ZRangeBy{Max: strconv.FormatInt(time.Now().Unix(), 10)}).Result() if err != nil { log.Printf("zrangeByScore error : %s", err) } else { for i, item := range results { log.Printf("zrangeByScore item[%s] : %s", strconv.Itoa(i), item) } }
- Zookeeper(github.com/samuel/go-zookeeper/zk):分布式协作服务客户端第三方开源库的实现,具体代码如下:
// watch option := zk.WithEventCallback(func(event zk.Event) { eventType := event.Type.String() log.Printf("event name : %s", eventType) }) // acl acl := zk.WorldACL(zk.PermAll) // root path path := "/go/zookeeper" conn,_,err := zk.Connect([]string{"127.0.0.1:2181"}, 5 * time.Second, option) if err != nil { panic(err) } // create znode _, err = conn.Create(path, []byte("duang"), 0, acl) if err != nil { log.Printf("create znode error : %s", err) } // set _, err = conn.Set(path, []byte("duang duang"), 1) if err != nil { log.Printf("set error : %s", err) } // get node and set watch data, stat, _, _ := conn.GetW(path) if data != nil { log.Println("zk get response:", string(data), ", stat:", stat.Version) } // exist znode exist, _, _, existErr := conn.ExistsW(path) if existErr != nil { log.Printf("exist znode error: %s", existErr) return } log.Printf("exist znode response : %s", strconv.FormatBool(exist)) // watch children children, _, _, err := conn.ChildrenW(path) if err != nil { log.Printf("watch children error: %s", err) } if len(children) > 0 { for item := range children { log.Printf("watch children : %s", item) } }
- Kafka(github.com/Shopify/sarama):kafka的第三方客户端实现,生产者和消费者实现如下:
// producer config := sarama.NewConfig() config.Producer.RequiredAcks = sarama.WaitForAll config.Producer.Partitioner = sarama.NewRandomPartitioner config.Producer.Return.Successes = true producer, err := sarama.NewSyncProducer([]string{"127.0.0.1:9092"}, config) if err != nil { panic(err) } defer producer.Close() // send msg param := make(map[string]string) param["name"] = "jack" param["sex"] = "male" js, err := json.Marshal(param) if err != nil { log.Printf("json err: %s", err.Error()) } else { msg := &sarama.ProducerMessage{} msg.Topic = "kafka_test" msg.Value = sarama.ByteEncoder(js) partition, offset, err := producer.SendMessage(msg) if err != nil { log.Printf("failed to produce message :%s", err.Error()) } log.Printf("partition:%d, offset: %d", partition, offset) } // consumer var wg sync.WaitGroup consumer, err := sarama.NewConsumer([]string{"127.0.0.1:9092"}, nil) if err != nil{ panic(err) } defer consumer.Close() partitionList, err := consumer.Partitions("kafka_test") // get topic all partitions if err != nil{ log.Println("Failed to get the list of partition: ",err) return } // recieve msg for partition := range partitionList{ pc, err := consumer.ConsumePartition("kafka_test", int32(partition), sarama.OffsetNewest) if err != nil{ log.Printf("Failed to start consumer for partition %d: %s", partition, err) return } wg.Add(1) go func(sarama.PartitionConsumer) { for msg := range pc.Messages(){ log.Printf("Partition:%d, Offset:%d, key:%s, value:%s", msg.Partition, msg.Offset, string(msg.Key),string(msg.Value)) } defer pc.AsyncClose() wg.Done() }(pc) } wg.Wait()
- ElasticSearch(github.com/olivere/elastic):ES的第三方客户端开源库,主要提供增、删、改、查和搜索的实现。
// init esClient, err := elastic.NewClient( elastic.SetURL("http://127.0.0.1:9200"), elastic.SetScheme("http"), // health check elastic.SetHealthcheck(true), elastic.SetHealthcheckTimeoutStartup(5*time.Second), elastic.SetHealthcheckTimeout(2*time.Second), elastic.SetHealthcheckInterval(60*time.Second), // sniffer elastic.SetSniff(true), elastic.SetSnifferInterval(15*time.Minute), elastic.SetSnifferTimeoutStartup(5*time.Second), elastic.SetSnifferTimeout(2*time.Second), elastic.SetSendGetBodyAs("GET"), ) if err != nil { panic(err) } // create param := `{"first_name":"jason","last_name":"kid","age":40}` resp, err := esClient.Index(). Index("es_test"). Type("employee"). Id("1"). BodyJson(param). Do(context.Background()) if err != nil { log.Printf("create error: %s", err) } else { log.Printf("Indexed tweet %s to index s%s, type %s", resp.Id, resp.Index, resp.Type) } // update res, err := esClient.Update(). Index("es_test"). Type("employee"). Id("1"). Doc(map[string]interface{}{"age": 88}). Do(context.Background()) if err != nil { log.Printf("update error: %s", err) } else { log.Printf("update age %s\n", res.Result) } // delete resDel, err := esClient.Delete(). Index("es_test"). Type("employee"). Id("1"). Do(context.Background()) if err != nil { log.Printf("delete error: %s", err) } else { log.Printf("delete result %s", resDel.Result) } // get resGet, err := esClient.Get(). Index("es_test"). Type("employee"). Id("1"). Do(context.Background()) if err != nil { log.Printf("get error: %s", err) } else if resGet.Found { log.Printf("Get document %s in version %d from index %s, type %s", resGet.Id, resGet.Version, resGet.Index, resGet.Type) } // search resQuery, err := esClient.Search("es_test"). Type("employee"). Query(elastic.NewQueryStringQuery("first_name:jason")). Do(context.Background()) if err != nil { log.Printf("query error: %s", err) } else if resQuery.Hits.TotalHits > 0 { for _, hit := range resQuery.Hits.Hits { b,_ := hit.Source.MarshalJSON() log.Printf("employee item : %s ", string(b)) } }
- Cron(github.com/robfig/cron):定时任务第三方库,支持克隆表达式,很强大。
c := cron.New() c.AddFunc("*/30 * * * * ?", func() { // to do something log.Println("run task ...") }) c.Start()
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK