http.Get
package main
import (
"fmt"
"net/http"
)
func main() {
host := "baidu.com"
url1 := "http://" + host
fmt.Printf("Send request to %q with method GET ...\n", url1)
// 第一个结果值的类型为 *http.Respons,为相应内容
// 第二个结果值为 error 类型,代表了在创建和发生 HTTP 请求、接受和解析 HTTP
// 相应过程中可能发生的错误
resp1, err := http.Get(url1)
if err != nil {
fmt.Printf("request sending error: %v\n", err)
return
}
defer resp1.Body.Close()
line1 := resp1.Proto + " " + resp1.Status
fmt.Printf("The first line of respones:\n%s\n", line1)
fmt.Println()
}
http.Client 类型中的 Transport 字段
代表着向网络发送 HTTP 请求,并从网络服务接收 HTTP 响应的操作过程。
package main
import (
"fmt"
"net/http"
"net"
"strings"
"time"
)
func main() {
myTransport := &http.Transport {
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer {
Timeout: 15 * time.Second,
KeepAlive: 15 * time.Second, // 用于底层 socket
DualStack: true,
}).DialContext,
// 最大空闲连接数
MaxIdleConns: 10,
// 访问每个网络服务的最大空闲连接数
MaxIdleConnsPerHost: 2,
// 空闲的连接在多久后应该被关闭
IdleConnTimeout: 30 * time.Second,
// 从客户端把请求完全递交给操作系统到
// 从操作系统系统那里接收到响应报文头的最大时长
ResponseHeaderTimeout: 0,
// 在客户端递交了请求报文头后,等待接收第一个响应报文头的最大时长
ExpectContinueTimeout: 1 * time.Second,
// 基于 TLS(Transport Layer Security)协议在被建立时握手阶段的超时时间
TLSHandshakeTimeout: 10 * time.Second,
}
myClient := http.Client {
Transport: myTransport,
Timeout: 20 * time.Second,
}
var logBuf strings.Builder
var diff time.Duration
defer func() {
logBuf.WriteString(
fmt.Sprintf("(elapsed time: %s)\n", diff))
fmt.Println(logBuf.String())
}()
url := "https://www.baidu.com"
logBuf.WriteString (
fmt.Sprintf("Send request to %q with method GET ...\n", url))
t1 := time.Now()
resp, err := myClient.Get(url)
diff = time.Now().Sub(t1)
if err != nil {
logBuf.WriteString(
fmt.Sprintf("request sending error: %v\n", err))
return
}
defer resp.Body.Close()
line2 := resp.Proto + " " + resp.Status
logBuf.WriteString(
fmt.Sprintf("The first line of response:\n%s\n", line2))
}
http.Server 类型的 ListenAndServer 方法
http.Server 类型的 ListenAndServe 方法的功能是:监听一个基于 TCP 协议的网络地址,并对接收到的 HTTP请求进行处理。
如果 Addr 字段正确,调用 net.Listen() 在网络地址上启动基于 TCP 协议的监听,然后检查 net.Listen() 返回的错误值,如果为 nil,调用 Serve() 准备接受和处理即将到来的 HTTP 请求。Serve() 会在一个 for 中不断调用 Accept()。
package main
import (
"fmt"
"log"
"net/http"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(2)
go startServer1(&wg)
go startServer2(&wg)
wg.Wait()
}
func startServer1(wg *sync.WaitGroup) {
defer wg.Done()
var httpServer1 http.Server
httpServer1.Addr = "127.0.0.1:8080"
// 由于没有定制 handler,所以响应 404
if err := httpServer1.ListenAndServe(); err != nil {
if err == http.ErrServerClosed {
log.Println("HTTP server 1 closed.")
} else {
log.Printf("HTTP server 1 error: %v\n", err)
}
}
}
func startServer2(wg *sync.WaitGroup) {
defer wg.Done()
mux1 := http.NewServeMux()
mux1.HandleFunc("/hi", func(w http.ResponseWriter, req *http.Request) {
if req.URL.Path != "/hi" {
http.NotFound(w, req)
return
}
name := req.FormValue("name")
if name == "" {
fmt.Fprint(w, "Welcome!")
} else {
fmt.Fprintf(w, "Welcome, %s!", name)
}
})
httpServer2 := http.Server {
Addr: "127.0.0.1:8081",
Handler: mux1,
}
if err := httpServer2.ListenAndServe(); err != nil {
if err == http.ErrServerClosed {
log.Println("HTTP server 2 closed.")
} else {
log.Printf("HTTP server 2 error: %v\n", err)
}
}
}