我有以下 for...range block ,它使用 goroutine 调用 url。
func callUrls(urls []string, reqBody interface{}) []*Response {
ch := make(chan *Response, len(urls))
for _, url := range urls {
somePostData := reqBody //this just seems to copy reference, not a deep copy
go func(url string, somePostData interface{}) {
//serviceMutex.Lock()
//defer serviceMutex.Unlock()
somePostData.(map[string]interface{})["someKey"] = "someval" //can be more deeper nested
//Data race - while executing above line it seems the original data is only getting modified, not the new local variable
//http post on url,
postJsonBody, _ := json.Marshal(somePostData)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(postJsonBody))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Connection", "Keep-Alive")
client := &http.Client{
Timeout: time.Duration(time.Duration(300) * time.MilliSecond),
}
response, err := client.Do(req)
response.Body.Close()
// return to channel accordingly
ch <- &Response{200, "url", "response body"}
}(url, somePostData)
}
//for block to return result.
}
每个goroutine func需要将修改后的post数据post到url。
但是使用 -race 运行会在修改后数据接口(interface)的行显示数据竞争。
我还尝试了 sync.Mutex Lock() 和 Unlock() 但它似乎阻止了整个应用程序。我不想使用 []bytes,因为修改 slice 似乎更消耗 CPU(在我看来)。
在这里避免数据竞争的最佳方法是什么。此外,连接似乎也没有被重用,导致 http 错误。有什么建议吗?
最佳答案
几个选项:
使用互斥量
这是最安全、最直接的。它看起来像你的 mutex 的范围可以简化为:
serviceMutex.Lock()
somePostData.(map[string]interface{})["someKey"] = "someval"
postJsonBody, _ := json.Marshal(somePostData)
serviceMutex.Unlock()
这应该对您的吞吐量有很大帮助。
让每个 goroutine 构建自己的 somePostData
根据您的数据结构,这应该允许每个 goroutine 不与任何其他 goroutine 共享数据,并为您提供安全性和速度提升。想象一下,与其传递本身可能包含大量引用的接口(interface){},不如传递一个能够构建请求主体的线程安全方法:
func callUrls(urls []string, buildReqBody func(...params...) interface{})
...
somePostData = buildReqBody(...params...)
关于go - 避免在带有接口(interface)的范围内的 goroutine 中进行数据竞争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57664430/
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做
我正在尝试使用在我的代码中是动态的Time.local来安排时间。在每个月的第一天,我传递的值是Time.local(2009,9,-1,0)。在PHP中,这会将时间设置为上个月的最后一天。在ruby中,我只是得到“ArgumentError:参数超出范围”。是我用错了方法还是什么?谢谢。 最佳答案 您应该使用DateTime类而不是Time。(您可能需要先require'date'并安装activesupportgem。)它比Time更通用,并且可以用DateTime.civil(2009,9-1,-1,0)做你想做的事。为天