rueidis 简介

简介 rueidis 是一个快速的Golang Redis客户端,支持客户端缓存、Auto Pipelining、泛型OM、RedisJSON、RedisBloom、RediSearch等功能。 Features Auto pipelining for non-blocking redis commands RESP3 中的客户端缓存 Pub/Sub, Sharded Pub/Sub, Streams Redis Cluster, Sentinel, RedisJSON, RedisBloom, RediSearch, RedisTimeseries, 等. 具有客户端缓存和乐观锁定的通用对象映射 具有客户端缓存的分布式锁 rueidis mock OpenTelemetry 集成 Hooks and other 集成 提供类似 Go-redis API 的适配器 需要注意的是由于使用了一些go1.20版本才有的特性,如果想要使用低版本go,必须安装相应的版本。 简单使用 package main import ( "context" "fmt" "github.com/redis/rueidis" ) func main() { // 创建redis客户端连接 client, err := rueidis.NewClient(rueidis.ClientOption{InitAddress: []string{"127.0.0.1:6379"}}) if err != nil { panic(err) } defer client.Close() ctx := context.Background() // 执行 redis set 命令 err = client.Do(ctx, client.B().Set().Key("key1").Value("val").Nx().Build()).Error() if err != nil { panic(err) } hm, err := client.Do(ctx, client.B().Get().Key("key1").Build()).ToString() if err != nil { panic(err) } fmt.Println(hm) } go-redis适配器 如何快速从 go-redis 切换到 rueidis 客户端呢,rueidis 提供了rueidiscompat.NewAdapter 方法,通过Adapter可以使用熟悉的go-redis中的方法。 ...

七月 8, 2023 · overstarry

Go wasi

WebAssembly是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C / C ++等语言提供一个编译目标,以便它们可以在Web上运行。它也被设计为可以与JavaScript共存,允许两者一起工作。 Go从1.11版本就开始支持将Go源码编译为wasm二进制文件,并在支持wasm的浏览器环境中运行。 不过WebAssembly绝不仅仅被设计为仅限于在Web浏览器中运行,核心的WebAssembly语言是独立于其周围环境的,WebAssembly完全可以通过API与外部世界互动。在Web上,它自然使用浏览器提供的现有Web API。然而,在浏览器之外,之前还没有一套标准的API可以让WebAssembly程序使用。这使得创建真正可移植的非Web WebAssembly程序变得困难。WebAssembly System Interface(WASI)是一个填补这一空白的倡议,它有一套干净的API,可以由多个引擎在多个平台上实现,并且不依赖于浏览器的功能(尽管它们仍然可以在浏览器中运行)。 Go 1.21将增加对WASI的支持,初期先支持WASI Preview1版本,之后会支持WASI Preview2版本,直至最终WASI API版本发布! go 编译支持 wasi 的程序 怎么样才能编译支持 wasi 的程序呢? 我们可以使用GOOS=wasip1 GOARCH=wasm将Go源码编译为支持WASI的wasm程序。下面是一个例子: 我们先编写一个简单的 go 程序: package main import "fmt" func main() { fmt.Println("Hello, World!") } 使用以下命令编译: GOARCH=wasm GOOS=wasip1 gotip build -o main.wasm main.go 编译后会得到 wasm 程序 main.wasm。 我们可以使用 wazero 运行编译后的 wasm 程序: $ curl https://wazero.io/install.sh $ wazero run main.wasm hello 其它 wasi 接口的支持是近期才添加的功能,我还尝试了一些其它的 go 程序,发现只有部分程序能够顺利运行,猜测是对 wasi 的支持不完全导致的。 ...

五月 2, 2023 · overstarry

gRPC服务反射协议

本文主要介绍 gRPC 的服务反射协议和相关的应用。 介绍 gRPC 服务反射协议 (server reflection) 是在 gRPC 服务端定义的一个服务,它能提供该服务器端上可公开使用的 gRPC 服务的信息,简单的来说,就是服务反射向客户端提供了服务端注册的服务的信息。 因此客户端不需要预编译服务定义就能与服务端交互了。 客户端想要与服务端程序进行通信,必须要有所定义的服务信息,需要编译生产客户端存根,借助 gRPC 服务反射协议,我们就可以无需编译服务定义就能通信。 使用 该如何开启服务反射协议呢? 很简单,只需要通过一行代码即可开启: reflection.Register() package main import ( "context" "flag" "fmt" "log" "net" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ecpb "google.golang.org/grpc/examples/features/proto/echo" hwpb "google.golang.org/grpc/examples/helloworld/helloworld" ) var port = flag.Int("port", 50051, "the port to serve on") // hwServer is used to implement helloworld.GreeterServer. type hwServer struct { hwpb.UnimplementedGreeterServer } // SayHello implements helloworld.GreeterServer func (s *hwServer) SayHello(ctx context.Context, in *hwpb.HelloRequest) (*hwpb.HelloReply, error) { return &hwpb.HelloReply{Message: "Hello " + in.Name}, nil } type ecServer struct { ecpb.UnimplementedEchoServer } func (s *ecServer) UnaryEcho(ctx context.Context, req *ecpb.EchoRequest) (*ecpb.EchoResponse, error) { return &ecpb.EchoResponse{Message: req.Message}, nil } func main() { flag.Parse() lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) if err != nil { log.Fatalf("failed to listen: %v", err) } fmt.Printf("server listening at %v\n", lis.Addr()) s := grpc.NewServer() // Register Greeter on the server. hwpb.RegisterGreeterServer(s, &hwServer{}) // Register RouteGuide on the same server. ecpb.RegisterEchoServer(s, &ecServer{}) // Register reflection service on gRPC server. reflection.Register(s) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } } 服务端开启服务反射协议后,就可以通过 gRPC CLI 工具来检查服务端了。这里就不多介绍了,接下来我们来看看服务反射协议在 kratos 中的使用。 ...

八月 27, 2022 · overstarry

Go进行浏览器网页截图

前言 在本文中将介绍使用 golang 进行加载某个网站并进行截图。 chromedp 我们将使用 chromedp 通过浏览器驱动来加载网页并截图。 具体的步骤如下: 1 启动 chrome 浏览器 2 加载网页 (还可进行其他浏览器操作) 3 截图并保存 需要注意的是项目使用了 Chrome 的驱动,如果没有 Chrome 将不能顺利运行,需要运行 https://hub.docker.com/r/chromedp/headless-shell/ 来进行 或运行其他 版本的 Chrome 。 安装 go get -u github.com/chromedp/chromedp 示例 package main import ( "context" "io/ioutil" "log" "github.com/chromedp/chromedp" ) func main() { ctx, cancel := chromedp.NewContext(context.Background(), chromedp.WithDebugf(log.Printf)) defer cancel() url := "https://www.minigame.vip/" filename := "minigame.png" var imageBuf []byte // 捕获某个元素的截图 if err := chromedp.Run(ctx, elementScreenshot(`https://pkg.go.dev/`, `img.Homepage-logo`, &imageBuf)); err != nil { log.Fatal(err) } if err := ioutil.WriteFile("elementScreenshot.png", imageBuf, 0644); err != nil { log.Fatal(err) } if err := chromedp.Run(ctx, ScreenshotTasks(url, &imageBuf)); err != nil { log.Fatal(err) } if err := ioutil.WriteFile(filename, imageBuf, 0644); err != nil { log.Fatal(err) } } func elementScreenshot(urlstr, sel string, res *[]byte) chromedp.Tasks { return chromedp.Tasks{ chromedp.Navigate(urlstr), chromedp.Screenshot(sel, res, chromedp.NodeVisible), } } func ScreenshotTasks(url string, imageBuf *[]byte) chromedp.Tasks { return chromedp.Tasks{ chromedp.Navigate(url), chromedp.FullScreenshot(imageBuf, 90), } } 上面的例子分别是对网页中的单个元素进行截图和对网页全局截图。 ...

八月 20, 2022 · overstarry

gopsutil介绍

简介 psutil 是一个使用 Python 编写的跨平台平台进程和系统利用率监控库,gopsutil 就是 psutil 的 go 语言实现。 使用 安装 go get github.com/shirou/gopsutil/v3 CPU 获取cpu基本信息 func getCpuInfo() { cpuInfos, err := cpu.Info() if err != nil { fmt.Printf("get cpu info failed, err:%v", err) } for _, ci := range cpuInfos { fmt.Println(ci) } for { percent, _ := cpu.Percent(time.Second, false) fmt.Printf("cpu percent:%v\n", percent) } } {"cpu":0,"vendorId":"GenuineIntel","family":"205","model":"","stepping":0,"physicalId":"BFEBFBFF000406E3","coreId":"","cores":4,"modelName":"Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz","mhz":2400,"cacheSize":0,"flags":[],"microcode":""} cpu percent:[40.625] cpu percent:[15] cpu percent:[9.615384615384617] cpu percent:[28.125] 获取cpu负载 func getCpuLoad() { info, err := load.Avg() if err != nil { panic(err) } fmt.Printf("%v\n", info) } 内存 获取内存 func getMemInfo() { memInfo, _ := mem.VirtualMemory() fmt.Printf("mem info:%v\n", memInfo) } mem info:{"total":8472920064,"available":1921372160,"used":6551547904,"usedPerce nt":77,"free":1921372160,"active":0,"inactive":0,"wired":0,"laundry":0,"buffers" :0,"cached":0,"writeBack":0,"dirty":0,"writeBackTmp":0,"shared":0,"slab":0,"srec laimable":0,"sunreclaim":0,"pageTables":0,"swapCached":0,"commitLimit":0,"commit tedAS":0,"highTotal":0,"highFree":0,"lowTotal":0,"lowFree":0,"swapTotal":0,"swap Free":0,"mapped":0,"vmallocTotal":0,"vmallocUsed":0,"vmallocChunk":0,"hugePagesT otal":0,"hugePagesFree":0,"hugePagesRsvd":0,"hugePagesSurp":0,"hugePageSize":0} 库的其他用法可以查看相应的官方文档。 ...

八月 13, 2022 · overstarry