resp, err := http.Get("<http://example.com/>")
...
resp, err := http.Post("<http://example.com/upload>", "image/jpeg", &buf)
...
resp, err := http.PostForm("<http://example.com/form>",
url.Values{"key": {"Value"}, "id": {"123"}})
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
// ...
For control over HTTP client headers, redirect policy ... etc, create a Client:
client := &http.Client{
CheckRedirect: redirectPolicyFunc,
}
resp, err := client.Get("<http://example.com>")
// ...
req, err := http.NewRequest("GET", "<http://example.com>", nil)
// ...
req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)
// ...
type Request struct {
...
URL *url.URL
...
Header Header
// Body must allow Read to be called concurrently with Close.
// In particular, calling Close should unblock a Read waiting
// for input.
Body io.ReadCloser
...
}
大多数 http 框架都是这样实现的,Body 这样的 流 Stream 数据只读一次,是因为持有的缓冲区的指针都是往前读的,如果一直持有缓冲区而不释放会出问题,可以想象一下,假如可以多次重复读,那么用户连接所产生的的内存占用的缓冲区有多大呢?什么时候释放呢?
在实际开发中,响应主体持有的资源可能会很大,所以并不会将其直接保存在内存中,只是持有数据流连接。当我们需要时,才会从服务器获取数据并返回。同时,考虑到应用重复读取数据的可能性很小,所以将其设计为一次性流(one-shot)
即“读取后立即关闭并释放资源”。
URL
type URL struct {
Scheme string
Opaque string // encoded opaque data
User *Userinfo // username and password information
Host string // host or host:port
Path string // path (relative paths may omit leading slash)
RawPath string // encoded path hint (see EscapedPath method)
ForceQuery bool // append a query ('?') even if RawQuery is empty
RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#'
RawFragment string // encoded fragment hint (see EscapedFragment method)
}
type Values map[string][]string
func (u *URL) Query() Values
func main() {
u, err := url.Parse("<http://bing.com/search?q=dotnet>")
if err != nil {
log.Fatal(err)
}
u.Scheme = "https"
u.Host = "google.com"
q := u.Query()
q.Set("q", "golang")
u.RawQuery = q.Encode()
fmt.Println(u) // <https://google.com/search?q=golang>
}
[scheme:][//[userinfo@]host][/]path[?query][#fragment]
What's in an HTTP response?
Golang 中客户端请求信息都封装到 Request
结构体,但发送给客户端的是 ResponseWriter
接口,用来处理 HTTP 响应
type ResponseWriter interface {
Header() Header
Write([]byte)(int, error)
WriteHeader(statusCode int)
}
func Home(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Welcome to my blog site")
}