HTTP Client
package main
import (
"bufio"
"fmt"
"net/http"
)
func main() {
resp, err := http.Get("https://siriusuna.top/%E6%8A%98%E8%85%BE%E6%97%A5%E5%BF%97/Golang")
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response status:", resp.Status)
scanner := bufio.NewScanner(resp.Body)
for i := 0; i < 5 && scanner.Scan(); i++ {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
panic(err)
}
}
/*
Response status: 200 OK
<!DOCTYPE html>
<html lang="zh" dir="ltr"><head><title>文件夹: 折腾日志/Golang | Siriusuna</title><meta charset="utf-8"/><link rel="preconnect" href="https://cdnjs.clo
udflare.com" crossorigin="anonymous"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><meta name="og:site_name" content="シリウ
スの砂"/><meta property="og:title" content="文件夹: 折腾日志/Golang | Siriusuna"/><meta property="og:type" content="website"/><meta name="twitter:card"
content="summary_large_image"/><meta name="twitter:title" content="文件夹: 折腾日志/Golang | Siriusuna"/><meta name="twitter:description" content="无
描述"/><meta property="og:description" content="无描述"/><meta property="og:image:alt" content="无描述"/><meta property="og:image" content="https://sir
iusuna.top/static/og-image.png"/><meta property="og:image:url" content="https://siriusuna.top/static/og-image.png"/><meta name="twitter:image" content=
"https://siriusuna.top/static/og-image.png"/><meta property="og:image:type" content="image/.png"/><meta property="twitter:domain" content="siriusuna.to
p"/><meta property="og:url" content="https://siriusuna.top/折腾日志/Golang/index"/><meta property="twitter:url" content="https://siriusuna.top/折腾日志
/Golang/index"/><link rel="icon" href="../../static/icon.png"/><meta name="description" content="无描述"/><meta name="generator" content="Quartz"/><lin
k rel="preconnect" href="https://cdn.jsdelivr.net"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css"/><script sr
c="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js" async></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lxgw-we
nkai-screen-webfont/1.7.0/style.css" integrity="sha512-A2sVEqmNCGCac7ji4czWLqCVSn28L0U5lSobS173H+gk+QTV6rH0EH0QEnYk5mz3KPRDmEr+GKM1hfdfLrsFpg==" crosso
rigin="anonymous" referrerpolicy="no-referrer"/><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/fira_code.css" integ
rity="sha512-LaxQmGd9k/pW51CsEy2nLIlbUXCgsyvUEVT5fSguN2b2OBwHjMi2aiUdEEXSMg8Jvy+bCB01as61aNrHnL2DYQ==" crossorigin="anonymous" referrerpolicy="no-refer
rer"/><link rel="stylesheet" href="https://fontsapi.zeoseven.com/442/main/result.css"/><link href="https://fonts.googleapis.com/css2?family=Monsieur+La
+Doulaise&display=swap" rel="stylesheet"/><link href="../../index.css" rel="stylesheet" type="text/css" data-persist="true"/><style>.expand-button
{
position: absolute;
display: flex;
float: right;
*/HTTP Server
The core conception in net/http in Go is Handler which is an interface:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}It takes a *Request and then write the response to ResponseWriter.
The response writer is used to fill in the HTTP response. Here our simple response is just "hello\n".
A common way to write a handler is by using the http.HandlerFunc adapter on functions with the appropriate signature.
(That means when we write a function with this signature, it will converse to http.HandlerFunc when it passed in http.HandleFunc(NO ‘S’))
e.g.,
func hello(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "hello\n")
}This handler does something a little more sophisticated
by reading all the HTTP request headers and echoing them into the response body.
func headers(w http.ResponseWriter, req *http.Request) {
for name, headers := range req.Header {
for _, h := range headers {
fmt.Fprintf(w, "%v: %v\n", name, h)
}
}
}We register our handlers on server routes using the http.HandleFunc convenience function.
It sets up the default router in the net/http package and takes a function as an argument.
func main() {
// Type conversion: From function to an function type `http.HandlerFunc` which implemented `Handler` interface.
http.HandleFunc("/hello", hello)
http.HandleFunc("/headers", headers)
// Finally, we call the `ListenAndServe` with the port and a handler.
// `nil` tells it to use the default router we’ve just set up.
http.ListenAndServe(":8090", nil)
}In practice, we’d better creating mux explicitly.
mux := http.NewServeMux()
mux.HandleFunc("/hello", hello)
http.ListenAndServe(":8090", mux)Note that the handler functions are executed concurrently.
Context
A Context carries deadlines, cancellation signals,
and other request-scoped values across API boundaries and goroutines.
package main
import (
"fmt"
"net/http"
"time"
)
func hello(w http.ResponseWriter, req *http.Request) {
ctx := req.Context() // Context can be access with `Context` method
fmt.Println("server: hello handler started")
defer fmt.Println("server: hello handler ended")
// Wait for a few seconds before sending a reply to the client.
// While working, keep an eye on the context’s Done() channel for a signal that
// we should cancel the work and return as soon as possible.
select {
case <-time.After(10 * time.Second):
fmt.Fprintln(w, "Hello")
case <-ctx.Done():
err := ctx.Err() // The context’s Err() method returns an error that explains why the Done() channel was closed.
fmt.Println("server:", err)
internalError := http.StatusInternalServerError
http.Error(w, err.Error(), internalError)
}
}
func main() {
http.HandleFunc("/hello", hello)
http.ListenAndServe(":8090", nil)
}
/*
$ go run cmd/context/context.go &
$ curl localhost:8090/hello
server: hello handler started
^C
server: context canceled
server: hello handler ended
*/