Features:
1
AngryPanda 2019-09-29 13:25:43 +08:00
reqeast 啥时候出
|
2
littlespider89 2019-09-29 13:36:01 +08:00
|
3
yixiang 2019-09-29 13:38:51 +08:00
reqwest - An easy and powerful Rust HTTP Client ( https://github.com/seanmonstar/reqwest)
一看还以为这个 rust 库被移植了。 |
4
winterssy OP @littlespider89 😅为什么要 PK,纯粹分享下自己的成果而已,无关其它。
|
5
winterssy OP @yixiang 本来是叫 grequests 的,只是昨晚偶然发现自己搞出来的玩意跟 rust reqwest 的 api 很像,就改成了现在这个名字,之前并不知道 reqwest...
|
6
www6688w 2019-09-29 15:21:47 +08:00
支持一下,,( ̄ m  ̄)
|
7
www6688w 2019-09-29 15:24:20 +08:00
楼主厉害,,我学了一段时间 Go,感觉还是没有基础吃透
个人英语能力太弱,Go 目前的生态库大部分都是英文文档,学起来吃力 |
8
seaguest 2019-09-29 16:48:19 +08:00
支持一下。
目前觉得最好的还是这个:github.com/imroc/req |
9
winterssy OP 更新:为避免跟 Rust reqwest 引起不必要的误解,项目更名为 sreq。新仓库地址: https://github.com/winterssy/sreq
|
10
snowwalf 2019-09-29 19:39:04 +08:00
目前工作中在用这个 https://github.com/go-resty/resty/
|
11
zealic 2019-09-29 19:54:28 +08:00
543 次点击 ∙ 3 人收藏 ∙ 1 人感谢
0 STAR |
12
winterssy OP @zealic #11 原项目名叫 reqwest 有 7 star 1 fork,后面遇到反馈说碰瓷 Rust 同名项目,删库更名重建了。star 不是我看重的,未曾想跟其它项目对比 /竞争,纯粹分享自己的成果而已。
|
14
Aether 2019-09-29 20:30:02 +08:00
我说怎么找不到了……还要翻进来重新点一次 star。黑心开发者!
|
15
fengkx 2019-09-29 20:46:31 +08:00
支持一下~
学习了代码。然后我想到一个问题。JSON()方法为什么不直接用 json.Decoder 呢。基于这个想法试了一下。 JSON 方法用 Deocder 可以这样 ```go func (r *Response) JSON(v interface{}) error { dec := json.NewDecoder(r.R.Body) return dec.Decode(v) } ``` Bench 代码 ```go func BenchmarkResponse_JSON(b *testing.B) { type testData struct { JSON struct { Msg string `json:"msg"` Num int `json:"num"` } `json:"json"` } ts := httptest.NewServer( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { dec := json.NewDecoder(r.Body) var data testData dec.Decode(&data.JSON) enc := json.NewEncoder(w) enc.Encode(data) })) resp := reqwest.Post(ts.URL). JSON( reqwest.Data{ "msg": "hello world", "num": 2019, }). Send(). EnsureStatusOk() b.ResetTimer() for i:=0;i<b.N;i++ { var retData testData resp.JSON(&retData) } } ``` 结果如下 ## Unmarshal ```plain $ go test -v -run="none" -bench="BenchmarkResponse_JSON" -benchtime="3s" -benchmem goos: linux goarch: amd64 pkg: github.com/winterssy/reqwest BenchmarkResponse_JSON-4 5000000 959 ns/op 544 B/op 2 allocs/op PASS ok github.com/winterssy/reqwest 5.895s ``` ## Decoder ```plain $ go test -v -run="none" -bench="BenchmarkResponse_JSON" -benchtime="3s" -benchmem goos: linux goarch: amd64 pkg: github.com/winterssy/reqwest BenchmarkResponse_JSON-4 10000000 713 ns/op 896 B/op 3 allocs/op PASS ok github.com/winterssy/reqwest 7.758s ``` 跟我设想的不太一样。还以为 Decoder 会更快。为什么会这样呢? |
16
whoami9894 2019-09-29 21:10:50 +08:00
|
17
winterssy OP @fengkx #15 我在 windows 上测了一下,结果反而跟你预期的一样,decoder 性能更好。这可能跟测试环境有关,网上查了一下,选择 decoder 更为合适,后续会使用 decoder 替换 unmarshal,感谢反馈。
stackoverflow 上类似的提问: https://stackoverflow.com/questions/21197239/decoding-json-using-json-unmarshal-vs-json-newdecoder-decode 附上测试结果: ## unmarshal goos: windows goarch: amd64 pkg: github.com/winterssy/sreq BenchmarkResponse_JSON-4 7664007 480 ns/op 544 B/op 2 allocs/op PASS ok github.com/winterssy/sreq 4.558s ## decoder goos: windows goarch: amd64 pkg: github.com/winterssy/sreq BenchmarkResponse_JSON-4 8721448 409 ns/op 896 B/op 3 allocs/op PASS ok github.com/winterssy/sreq 4.386s |
18
winterssy OP @fengkx #15 不对,你的测试结果也表示 decoder 更快吧。decoder 比 unmarshal 更快,但貌似需要更多的内存分配次数跟空间
|
19
justin2018 2019-09-29 22:39:39 +08:00
nice 已 start
|
20
deletelazy 2019-09-29 22:41:41 +08:00
你这个库有点问题啊,不是 thread-safe 的。。
|
21
deletelazy 2019-09-29 22:46:02 +08:00
@deletelazy 额,似乎要手动加锁。。感觉不是太友好
|
22
deletelazy 2019-09-29 22:52:44 +08:00
似乎并发 GET,POST 等也有问题
package main import ( "fmt" ) func main() { cs := make(chan *Client, 100) for i := 0; i < 10; i++ { go func(i int) { if i%2 == 1 { cs <- Get("123") } else { cs <- Post("456") } }(i) } for { select { case c := <-cs: fmt.Println(c.method, c.url) } } } |
23
winterssy OP @deletelazy #22 因为是链式操作,自动加锁就要每一步都加锁,这样不是很好,所以改成了手动加锁。而且你的测试例子明显就有问题,Get("123"),Post("456") 无论你创建多少个都是共享同一个 client——std,如果你真要这么玩,先 New()一个。
func main() { cs := make(chan *Client, 100) for i := 0; i < 10; i++ { go func(i int) { if i%2 == 1 { cs <- New().Get("123") } else { cs <- New().Post("456") } }(i) } for { select { case c := <-cs: fmt.Println(c.method, c.url) } } } |
24
deletelazy 2019-09-30 00:50:02 +08:00
并发请求都要加锁的话效率是不是太低了
如果并发请求使用每次 New 的方式,创建一堆对象浪费内存不说,每个请求新建一个 transport,连接也无法复用 而且每次并发请求都要 New 的话,那这些全局方法还有什么意义呢 |
25
winterssy OP @deletelazy 并发不加锁如何解决数据竞争问题?而且并发你不需要 New,会复用 http client,这里提到 New 只是针对你贴出的代码而言
|
26
winterssy OP @deletelazy 提出问题前请先仔细阅读 api 文档
|
27
deletelazy 2019-09-30 01:11:20 +08:00 via iPhone
那你可以看下其他的 http 库或者看下 http.Get
的实现有没加锁 |
28
winterssy OP @deletelazy 这根本没有可比性,net/http 在底层就实现了线程安全。而 sreq 是对 http api 的上层封装,它的设计决定了要加锁。且目前大多基于 net/http 封装的 request 库要么不支持并发安全,要么每次请求前克隆一份配置,要么加锁。结合具体场景分析,别章口就来😓
|