我编写了独立调用多个http请求并合并结果的go代码。
有时组合方法会缺少值。
func profile(req *http.Request) (UserMe, error, UserRating, error) {
wgcall := &sync.WaitGroup{}
uChan := make(chan ResUser)
rChan := make(chan ResRating)
// variable inits
var meResp UserMe
var ratingResp UserRating
go func() {
res := <-uChan
meResp = res.Value
}()
go func() {
res := <-rChan
ratingResp = res.Value
}()
wgcall.Add(2)
go me(req, wgcall, uChan)
go rate(req, wgcall, rChan)
wgcall.Wait()
logrus.Info(meResp) // sometimes missing
logrus.Info(ratingResp) // sometimes missing
return meResp, meErr, ratingResp, ratingErr
}
但是 me 和 rating 调用会按预期返回来自 api 请求的值。
func me(req *http.Request, wg *sync.WaitGroup, ch chan ResUser) {
defer wg.Done()
// http call return value correclty
me := ...
ch <- ResUser{
Value := // value from rest
}
logrus.Info(fmt.Sprintf("User calls %v" , me)) // always return the values
close(ch)
}
func rate(req *http.Request, wg *sync.WaitGroup, ch chan ResRating) {
defer wg.Done()
// make http call
rating := ...
ch <- ResRating{
Value := // value from rest
}
logrus.Info(fmt.Sprintf("Ratings calls %v" , rating)) // always return the values
close(ch)
}
问题是:配置文件函数上的 meResp 和 ratingResp 并不总是获取值。有时只有 meResp 或 ratingResp,有时两者都符合预期。
但是我和 rate 函数调用总是获取值。
能帮我解决这个问题吗?
最佳答案
有一个 race condition在您的代码中。
没有任何障碍可以确保从 uChan 和 rChan 读取的 profile 方法中的 goroutines 已经填充了变量 meResp 和 ratingResp 在您从 profile 返回之前。
您可以通过在 profile 中放弃使用 channel 和内联声明的 goroutines 来极大地简化您的代码。相反,只需直接填充响应值。在这种情况下,使用 channel 或 goroutines 读取它们没有任何好处,因为您只打算发送一个值,并且您要求两个 HTTP 调用产生的值在返回之前存在。
您可以通过修改 me 和 rate 的签名来接收指向写入其输出的位置的指针,或者通过用一个小函数包装它们的调用来实现此目的它接收它们的输出值并填充 profile 中的值。重要的是,WaitGroup 应该只在 值被填充后发出信号:
wgcall := &sync.WaitGroup{}
var meResp UserMe
var ratingResp RatingMe
wgcall.Add(2)
// The "me" and "rate" functions should be refactored to
// drop the wait group and channel arguments.
go func() {
meResp = me(req)
wgcall.Done()
}()
go func() {
ratingResp = rate(req)
wgcall.Done()
}()
wgcall.Wait()
// You are guaranteed that if "me" and "rate" returned valid values,
// they are populated in "meResp" and "ratingResp" at this point.
// Do whatever you need here, such as logging or returning.
关于golang 发出并发请求并合并响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52498618/
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
是否可以在PyYAML或Ruby的Psych引擎中禁用创建anchor和引用(并有效地显式列出冗余数据)?也许我在网上搜索时遗漏了一些东西,但在Psych中似乎没有太多可用的选项,而且我也无法确定PyYAML是否允许这样做.基本原理是我必须序列化一些数据并将其以可读的形式传递给一个不是真正的技术同事进行手动验证。有些数据是多余的,但我需要以最明确的方式列出它们以提高可读性(anchor和引用是提高效率的好概念,但不是人类可读性)。Ruby和Python是我选择的工具,但如果有其他一些相当简单的方法来“展开”YAML文档,它可能就可以了。 最佳答案
在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.
我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)
在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g
我试图像这样在我的测试用例中执行获取:request.env['CONTENT_TYPE']='application/json'get:index,:application_name=>"Heka"虽然,它失败了:ActionView::MissingTemplate:Missingtemplatealarm_events/indexwith{:handlers=>[:builder,:haml,:erb,:rjs,:rhtml,:rxml],:locale=>[:en,:en],:formats=>[:html]尽管在我的Controller中我有:respond_to:html,
如果使用rspec请求花费的时间太长,我该如何测试行为?我正在考虑使用线程来模拟这个:describe"Test"doit"shouldtimeoutiftherequesttakestoolong"dolambda{thread1=Thread.new{#net::httprequesttogoogle.com}thread2=Thread.new{sleep(xxseconds)}thread1.jointhread2.join}.shouldraise_errorendend我想确保在第一次发出请求后,另一个线程“启动”,在这种情况下只是休眠xx秒。然后我应该期望请求超时,因为执
假设我有:get'/'do$random=Random.rand()response.body=$randomend如果我每秒有数千个请求到达/,$random是否会被共享并“泄漏”到上下文之外,或者它会像getblock的“本地”变量一样?我想如果它是在get'/'do的上下文之外定义的,它确实会被共享,但我想知道在ruby中是否有我不知道的$机制。 最佳答案 ThispartoftheSinatraREADMEaboutscopeisalwayshelpfultoread但是,如果您只需要为请求保留变量,那么我认为我建议使用