使用Singleflight实现Golang代码优化

 更新时间:2023年09月05日 11:24:09   作者:洛天枫  
有许多方法可以优化代码以提高效率,减少运行进程就是其中之一,本文我们就来学习一下如何通过使用一个Go包Singleflight来减少重复进程,从而优化Go代码吧

介绍

有许多方法可以优化代码以提高效率,减少运行进程就是其中之一。在本文中,我们将看到如何通过使用一个Go包Singleflight来减少重复进程,从而优化Go代码。

问题

假设你有一个web应用,它每秒有10个请求(RPS)。根据您所知道的数据,其中一些请求具有相同的模式,实际上可以生成相同的结果,这意味着实际上存在冗余流程。

从上面的插图中,我们知道用户1和用户2想要相同的东西,但最终,我们(大多数情况下)分别处理这两个请求。

解决方案

Singleflight是可以解决这类问题的Go包之一,如文档中所述,它提供了重复函数调用抑制机制。

很酷,如果我们知道我们要调用的函数是重复的,我们就可以减少处理的函数的数量,让我们看看在现实世界中如何使用它。

实现

我们将创建两个程序,server.goclient.go

server.go — 将作为web服务,可以接收 /api/v1/get_something 的请求,参数名为name

// server.go
package main
import (
	"fmt"
	"net/http"
)
func main() {
	http.HandleFunc("/api/v1/get_something", func(w http.ResponseWriter, r *http.Request) {
		name := r.URL.Query().Get("name")
		response := processingRequest(name)
		_, _ = fmt.Fprint(w, response)
	})
	err := http.ListenAndServe(":15001", nil)
	if err != nil {
		fmt.Println(err)
	}
}
func processingRequest(name string) string {
	fmt.Println("[DEBUG] processing request..")
	return "Hi there! You requested " + name
}

client.go — 将作为一个客户端,向web服务发出5个并发请求(你可以在变量totalRequests中设置这个数字)。

// client.go
package main
import (
	"io"
	"log"
	"net/http"
	"sync"
)
func main() {
	var wg sync.WaitGroup
	endpoint := "http://localhost:15001/api/v1/get_something?name=something"
	totalRequests := 5
	for i := 0; i < totalRequests; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			makeAPICall(endpoint)
		}(i)
	}
	wg.Wait()
}
func makeAPICall(endpoint string) {
	resp, err := http.Get(endpoint)
	if err != nil {
		log.Fatalln(err)
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
	}
	result := string(body)
	log.Printf(result)
}

首先,我们可以运行 server.go,然后继续执行 client.go。我们将在服务器脚本的终端中看到如下内容:

[DEBUG] processing request.. 
[DEBUG] processing request.. 
[DEBUG] processing request.. 
[DEBUG] processing request.. 
[DEBUG] processing request..

客户端的输出是这样的:

2023/09/05 10:29:34 Hi there! You requested something
2023/09/05 10:29:34 Hi there! You requested something
2023/09/05 10:29:34 Hi there! You requested something
2023/09/05 10:29:34 Hi there! You requested something
2023/09/05 10:29:34 Hi there! You requested something

这是正确的,因为我们从客户端发送了五个请求,并在服务器中处理了这五个请求。

现在让我们在代码中实现Singleflight,这样它会更有效率。

// server.go
package main
import (
	"fmt"
	"net/http"
	"golang.org/x/sync/singleflight"
)
var g = singleflight.Group{}
func main() {
	http.HandleFunc("/api/v1/get_something", func(w http.ResponseWriter, r *http.Request) {
		name := r.URL.Query().Get("name")
		response, _, _ := g.Do(name, func() (interface{}, error) {
			result := processingRequest(name)
			return result, nil
		})
		_, _ = fmt.Fprint(w, response)
	})
	err := http.ListenAndServe(":15001", nil)
	if err != nil {
		fmt.Println(err)
	}
}
func processingRequest(name string) string {
	fmt.Println("[DEBUG] processing request..")
	return "Hi there! You requested " + name
}

重新启动服务器并再次运行客户端程序后,服务器的终端显示如下:

[DEBUG] processing request..
[DEBUG] processing request..

客户端的输出还是没有变化:

2023/09/05 10:32:49 Hi there! You requested something
2023/09/05 10:32:49 Hi there! You requested something
2023/09/05 10:32:49 Hi there! You requested something
2023/09/05 10:32:49 Hi there! You requested something
2023/09/05 10:32:49 Hi there! You requested something

太好了!所有客户端都得到了预期的响应,但是现在我们的服务器只处理了两个请求。想象一下,如果您处理数千个类似的请求,您将带来多大的效率,这是惊人的!

结论

在本文中,我们了解了Singleflight在优化代码方面的强大功能。不仅仅是处理一个web请求,你还可以将它的用例扩展到其他事情上,比如从数据库中获取数据等等。

还有一些我在本文中没有涉及的内容,例如Singleflight的过程失败会怎样,以及我们如何缓存它。

以上就是使用Singleflight实现Golang代码优化的详细内容,更多关于go Singleflight代码优化的资料请关注脚本之家其它相关文章!

相关文章

  • Golang异常处理之优雅地控制和处理异常

    Golang异常处理之优雅地控制和处理异常

    在Golang中,异常处理是非常重要的一部分,能够有效地控制和处理代码中的异常情况。通过Golang的异常处理机制,可以优雅地捕获和处理异常,保障代码的可靠性和稳定性。同时,Golang还提供了丰富的工具和API,帮助开发者更加轻松地进行异常处理
    2023-04-04
  • go中string、int、float相互转换的实现示例

    go中string、int、float相互转换的实现示例

    本文主要介绍了go中string、int、float相互转换的实现示例,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Go Web框架gin的入门教程

    Go Web框架gin的入门教程

    本篇文章主要介绍了Go Web框架gin的入门教程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • 解决 Golang VS Code 插件下载安装失败的问题

    解决 Golang VS Code 插件下载安装失败的问题

    这篇文章主要介绍了解决 Golang VS Code 插件下载安装失败,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • Go实现生产随机密码的示例代码

    Go实现生产随机密码的示例代码

    这篇文章主要为大家详细介绍了如何利用Go实现生产随机密码的,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2023-09-09
  • golang中gin框架接入jwt使用token验证身份

    golang中gin框架接入jwt使用token验证身份

    本文主要介绍了golang中gin框架接入jwt使用token验证身份,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • 详解Go中Set的实现方式

    详解Go中Set的实现方式

    这篇文章主要介绍了详解Go中Set的实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • GO语言中err接口及defer延迟异常处理分析

    GO语言中err接口及defer延迟异常处理分析

    这篇文章主要为大家介绍了GO语言中err接口及defer延迟异常处理的示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Go语言快速入门图文教程

    Go语言快速入门图文教程

    Go是 Goolge 开发的一种静态型、编译型、并发型,并具有垃圾回收功能的语言,Go 语言上手非常容易,它的风格类似于 C 语言,Go 语言号称是互联网时代的 C 语言,那么它到底有多火呢,一起看看吧
    2021-05-05
  • golang rate令牌桶源码分析实现方式

    golang rate令牌桶源码分析实现方式

    这篇文章主要介绍了golang rate令牌桶源码分析实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07

最新评论