Boost Go HTTP Performance with fasthttp: Practical API Guide
This article explores the fasthttp library as a high‑performance alternative to Go's net/http client, demonstrates basic and advanced API usage with object pools, shows how to set up a mock test server, and provides complete Go unit‑test examples with output verification.
Why fasthttp?
After learning the standard net/http client, the author discovered github.com/valyala/fasthttp, which claims up to ten times the performance of net/http. The library achieves this partly by using two sync.Pool objects ( requestPool and responsePool) to reduce memory allocations during high‑throughput requests.
Basic API Demonstration
package ft
import (
"encoding/json"
"fmt"
"funtester/task"
"github.com/valyala/fasthttp"
)
func FastGet(url string, args map[string]interface{}) ([]byte, error) {
uri := url + "?" + task.ToValues(args)
_, resp, err := fasthttp.Get(nil, uri)
if err != nil {
fmt.Println("请求失败:", err.Error())
return nil, err
}
return resp, err
}
func FastPostForm(url string, args map[string]interface{}) ([]byte, error) {
// Fill form similar to net/url
params := &fasthttp.Args{}
for s, i2 := range args {
sprintf := fmt.Sprintf("%v", i2)
params.Add(s, sprintf)
}
_, resp, err := fasthttp.Post(nil, url, params)
if err != nil {
fmt.Println("请求失败:", err.Error())
return nil, err
}
return resp, nil
}
func FastPostJson(url string, args map[string]interface{}) ([]byte, error) {
req := &fasthttp.Request{}
req.SetRequestURI(url)
marshal, _ := json.Marshal(args)
req.SetBody(marshal)
// Content‑type is optional for the server side
req.Header.SetContentType("application/json")
req.Header.SetMethod("POST")
resp := &fasthttp.Response{}
if err := fasthttp.Do(req, resp); err != nil {
fmt.Println("请求失败:", err.Error())
return nil, err
}
return resp.Body(), nil
}FastGet and FastPostForm use the default request acquisition provided by fasthttp, while FastPostJson builds a custom request.
The call to req.Header.SetContentType is optional; most servers can parse the body regardless of the header.
High‑Performance API Demonstration (Object Pool)
package task
import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/valyala/fasthttp"
"log"
"time"
)
var FastClient fasthttp.Client = fastClient()
func FastGet(url string, args map[string]interface{}) *fasthttp.Request {
req := fasthttp.AcquireRequest()
req.Header.SetMethod("GET")
values := ToValues(args)
req.SetRequestURI(url + "?" + values)
return req
}
func FastPostJson(url string, args map[string]interface{}) *fasthttp.Request {
req := fasthttp.AcquireRequest()
req.Header.SetContentType("application/json")
req.Header.SetMethod("POST")
req.SetRequestURI(url)
marshal, _ := json.Marshal(args)
req.SetBody(marshal)
return req
}
func FastPostForm(url string, args map[string]interface{}) *fasthttp.Request {
req := fasthttp.AcquireRequest()
req.Header.SetMethod("POST")
req.SetRequestURI(url)
marshal, _ := json.Marshal(args)
req.BodyWriter().Write([]byte(ToValues(args)))
req.BodyWriter().Write(marshal)
return req
}
func FastResponse(request *fasthttp.Request) ([]byte, error) {
response := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(response)
defer fasthttp.ReleaseRequest(request)
if err := FastClient.Do(request, response); err != nil {
log.Println("响应出错了")
return nil, err
}
return response.Body(), nil
}
func DoGet(url string, args map[string]interface{}) ([]byte, error) {
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
req.Header.SetMethod("GET")
values := ToValues(args)
req.SetRequestURI(url + "?" + values)
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp)
if err := FastClient.Do(req, resp); err != nil {
fmt.Println("请求失败:", err.Error())
return nil, err
}
return resp.Body(), nil
}
func fastClient() fasthttp.Client {
return fasthttp.Client{
Name: "FunTester",
NoDefaultUserAgentHeader: true,
TLSConfig: &tls.Config{InsecureSkipVerify: true},
MaxConnsPerHost: 2000,
MaxIdleConnDuration: 5 * time.Second,
MaxConnDuration: 5 * time.Second,
ReadTimeout: 5 * time.Second,
WriteTimeout: 5 * time.Second,
MaxConnWaitTimeout: 5 * time.Second,
}
}Test Service (Moco Framework)
package com.mocofun.moco.main
import com.funtester.utils.ArgsUtil
import com.mocofun.moco.MocoServer
import org.apache.tools.ant.taskdefs.condition.And
class Share extends MocoServer {
static void main(String[] args) {
def util = new ArgsUtil(args)
def server = getServer(util.getIntOrdefault(0, 12345))
server.get(both(urlStartsWith("/test"), existArgs("code"))).response("get请求")
server.post(both(urlStartsWith("/test"), existForm("fun"))).response("post请求form表单")
server.post(both(urlStartsWith("/test"), existParams("fun"))).response("post请求json表单")
server.get(urlStartsWith("/qps")).response(qps(textRes("恭喜到达QPS!"), 1))
server.response("Have Fun ~ Tester !")
def run = run(server)
waitForKey("fan")
run.stop()
}
}Go Unit Tests for the Wrapper
package test
import (
"funtester/ft"
"funtester/task"
"log"
"testing"
)
const url = "http://localhost:12345/test"
func args() map[string]interface{} {
return map[string]interface{}{"code": 32, "fun": 32, "msg": "324"}
}
func TestGet(t *testing.T) {
get := task.FastGet(url, args())
res, err := task.FastResponse(get)
if err != nil { t.Fail() }
v := string(res)
log.Println(v)
if v != "get请求" { t.Fail() }
}
func TestPostJson(t *testing.T) {
post := task.FastPostJson(url, args())
res, err := task.FastResponse(post)
if err != nil { t.Fail() }
v := string(res)
log.Println(v)
if v != "post请求json表单" { t.Fail() }
}
func TestPostForm(t *testing.T) {
post := task.FastPostForm(url, args())
res, err := task.FastResponse(post)
if err != nil { t.Fail() }
v := string(res)
log.Println(v)
if v != "post请求form表单" { t.Fail() }
}
// Tests that use the original ft package directly
func TestGetNor(t *testing.T) {
res, err := ft.FastGet(url, args())
if err != nil { t.Fail() }
v := string(res)
log.Println(v)
if v != "get请求" { t.Fail() }
}
func TestPostJsonNor(t *testing.T) {
res, err := ft.FastPostJson(url, args())
if err != nil { t.Fail() }
v := string(res)
log.Println(v)
if v != "post请求json表单" { t.Fail() }
}
func TestPostFormNor(t *testing.T) {
res, err := ft.FastPostForm(url, args())
if err != nil { t.Fail() }
v := string(res)
log.Println(v)
if v != "post请求form表单" { t.Fail() }
}Test Report Output
=== RUN TestGet
2021/10/18 18:56:49 get请求
--- PASS: TestGet (0.01s)
=== RUN TestPostJson
2021/10/18 18:56:49 post请求json表单
--- PASS: TestPostJson (0.00s)
=== RUN TestPostForm
2021/10/18 18:56:49 post请求form表单
--- PASS: TestPostForm (0.00s)
=== RUN TestGetNor
2021/10/18 18:56:49 get请求
--- PASS: TestGetNor (0.00s)
=== RUN TestPostJsonNor
2021/10/18 18:56:49 post请求json表单
--- PASS: TestPostJsonNor (0.00s)
=== RUN TestPostFormNor
2021/10/18 18:56:49 post请求form表单
--- PASS: TestPostFormNor (0.00s)
=== RUN TestStageJSONSigned-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
