From 84a0b9fc6f51eb33e7d0a1b5a12592854e838e04 Mon Sep 17 00:00:00 2001 From: liujian Date: Mon, 11 Sep 2023 11:20:17 +0800 Subject: [PATCH] Update xutil --- README.md | 12 +++++++++--- xconv/conv.go | 16 ++++++++++++++++ xhttp/options.go | 9 ++++++++- xhttp/request.go | 7 +++++-- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 06ddd36..b53a9d1 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,10 @@ go get github.com/mix-go/xutil | Function | Description | |----------------------------------------------------------------------------------|----------------------------------| | xhttp.Request(method string, u string, opts ...RequestOption) (*Response, error) | Execute an http request. | +| xhttp.WithBody(body Body) RequestOption | Set configuration item | +| WithHeader(header http.Header) RequestOption | Set configuration item | +| WithContentType(contentType string) RequestOption | Set configuration item | +| WithTimeout(timeout time.Duration) RequestOption | Set configuration item | | xhttp.BuildJSON(v interface{}) Body | Generate json string | | xhttp.BuildQuery(m map[string]string) Body | Generate urlencoded query string | @@ -33,9 +37,11 @@ go get github.com/mix-go/xutil ## xconv -| Function | Description | -|---------------------------------------------------------|------------------------| -| xconv.StructToMap(i interface{}) map[string]interface{} | Convert struct to map. | +| Function | Description | +|---------------------------------------------------------|-----------------------------------| +| xconv.StructToMap(i interface{}) map[string]interface{} | Convert struct to map. | +| xconv.StringToBytes(s string) []byte | Convert string to bytes (0 copy). | +| xconv.BytesToString(b []byte) string | Convert bytes to bytes (0 copy). | ## xcrypt diff --git a/xconv/conv.go b/xconv/conv.go index 175db9a..952612b 100644 --- a/xconv/conv.go +++ b/xconv/conv.go @@ -3,8 +3,24 @@ package xconv import ( "reflect" "strings" + "unsafe" ) +// StringToBytes converts string to byte slice without a memory allocation. +func StringToBytes(s string) []byte { + return *(*[]byte)(unsafe.Pointer( + &struct { + string + Cap int + }{s, len(s)}, + )) +} + +// BytesToString converts byte slice to string without a memory allocation. +func BytesToString(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} + // StructToMap Convert struct to map. // This function first tries to use the bson tag, and if the bson tag does not exist, it will use the json tag. // if both bson and json tags do not exist, then it will use the field name as the key. Additionally, diff --git a/xhttp/options.go b/xhttp/options.go index c96d3d3..732c949 100644 --- a/xhttp/options.go +++ b/xhttp/options.go @@ -1,6 +1,7 @@ package xhttp import ( + "github.com/mix-go/xutil/xconv" "net/http" "time" ) @@ -67,8 +68,14 @@ func WithBody(body Body) RequestOption { }} } +func WithBodyBytes(body []byte) RequestOption { + return &funcRequestOption{func(opt *requestOptions) { + opt.Body = body + }} +} + func WithBodyString(body string) RequestOption { return &funcRequestOption{func(opt *requestOptions) { - opt.Body = Body(body) + opt.Body = xconv.StringToBytes(body) }} } diff --git a/xhttp/request.go b/xhttp/request.go index 1e8156d..fb8954a 100644 --- a/xhttp/request.go +++ b/xhttp/request.go @@ -1,6 +1,7 @@ package xhttp import ( + "github.com/mix-go/xutil/xconv" "io" "net/http" "net/url" @@ -15,7 +16,7 @@ type Response struct { type Body []byte func (t Body) String() string { - return string(t) + return xconv.BytesToString(t) } func newResponse(r *http.Response) *Response { @@ -46,9 +47,11 @@ func Request(method string, u string, opts ...RequestOption) (*Response, error) req := &http.Request{ Method: method, URL: URL, - Body: io.NopCloser(strings.NewReader(opt.Body.String())), Header: opt.Header, } + if opt.Body != nil { + req.Body = io.NopCloser(strings.NewReader(opt.Body.String())) + } r, err := cli.Do(req) resp := newResponse(r) return resp, err