通过Hello World Web服务器宣告你的存在
package main
import(
"net/http"
)
func helloWorld(w http.ResponseWriter,r *http.Request){
w.Write([]byte("Hello world\n"))
}
func main(){
http.HandleFunc("/",helloWorld)
http.ListenAndServe(":8000",nil)
}
- 导入net/http包
- 在main函数中,使用方法HandleFunc创建了路由/,这个方法接受一个模式和一个函数,其中前者描述了路径,而后者指定如何对发送到该路径的请求做出响应
- 函数helloWorld接受一个http.ResponseWriter和一个指向请求的指针。这意味着在这个函数中,可产看或操作请求,再将相应返回给客户端。在这里,使用了方法Write来生成相应,这个方法生成的HTTP响应包含状态、报头和响应体。[]byte声明了一个字节切片并将字符串值转为字节。这意味着方法Write可以使用[]byte,因为这个方法将一个字节切片作为参数
- 为响应客户端,使用了方法ListenAndServe来启动一个服务器,这个服务器监听localhost和端口8000
查看请求和响应
使用GIT发出请求
可以使用GIT工具来对服务器发出请求,这样就不用打开浏览器
//运行服务器
go run test.go
//使用gitBash发出请求
curl -is http://localhost:8000
//结果
//HTTP/1.1 200 OK
//Date: Thu, 28 Jan 2021 14:21:46 GMT
//Content-Length: 12
//Content-Type: text/plain; charset=utf-8
//Hello world
- 这个响应使用的协议是HTTP1.1,状态码为200
- 报头Date详细地描述了响应的发送时间
- 报头Content-Length详细的指出了响应的长度,为12字节
- 报头Content-Type指出了内容的类型以及使用的编码
- 最后输出的是响应体,这里是hello world
详谈路由
HandleFunc用于注册对URL地址映射进行响应的函数
- 路由器默认将没有指定处理程序的请求定向到/
- 路由必须完全匹配,例如:对于向/users发出的请求,将定向到/,因为这里末尾少了斜杠
- 路由器不关心请求的类型,而只管将路由匹配的请求传递给响应的处理程序
处理404错误
默认路由器的行为是将所有没有指定处理程序的请求都定向到/,因此我们可以对前面的程序进行修改,让它在路径不存在时,返回404错误
package main
import(
"net/http"
)
func helloWorld(w http.ResponseWriter,r *http.Request){
if r.URL.Path !="/"{
http.NotFound(w,r)
return
}
w.Write([]byte("Hello world\n"))
}
func main(){
http.HandleFunc("/",helloWorld)
http.ListenAndServe(":8000",nil)
}
// $ curl -is http://localhost:8000
// HTTP/1.1 200 OK
// Date: Thu, 28 Jan 2021 14:30:33 GMT
// Content-Length: 12
// Content-Type: text/plain; charset=utf-8
// Hello world
// $ curl -is http://localhost:8000/user
// HTTP/1.1 404 Not Found
// Content-Type: text/plain; charset=utf-8
// X-Content-Type-Options: nosniff
// Date: Thu, 28 Jan 2021 14:30:57 GMT
// Content-Length: 19
// 404 page not found
设置报头
在创建HTTP服务器时,经常需要设置响应的报头
w.Header().Set("Content-Type","application/json;charset=utf-8")
只要这行代码是在响应被发送给客户端之前执行的,这个报头就会被添加到响应中
package main
import(
"net/http"
)
func helloWorld(w http.ResponseWriter,r *http.Request){
if r.URL.Path !="/"{
http.NotFound(w,r)
return
}
w.Header().Set("Content-Type","application/json;charset=utf-8")
w.Write([]byte("Hello world\n"))
}
func main(){
http.HandleFunc("/",helloWorld)
http.ListenAndServe(":8000",nil)
}
// $ curl -is http://localhost:8000
// HTTP/1.1 200 OK
// Content-Type: application/json;charset=utf-8
// Date: Thu, 28 Jan 2021 14:45:03 GMT
// Content-Length: 12
// Hello world
响应以不同类型的内容
响应客户端时,HTTP服务器通常提供多种类型的内容。一些常用的内容类型包括text/plain、text/html、application/json和application/xml。如果服务器支持多种类型的内容,客户端可使用Accept报头请求特定类型的内容。这意味着同一个URL可能向浏览器提供HTML
package main
import(
"net/http"
)
func helloWorld(w http.ResponseWriter,r *http.Request){
if r.URL.Path !="/"{
http.NotFound(w,r)
return
}
switch r.Header.Get("Accept"){
case "application/json":
w.Header().Set("Content-Type","application/json ; charset=utf-8")
w.Write([]byte(`{"message":"Hello World"}`))
case "application/xml":
w.Header().Set("Content-Type","application/xml;charset =utf-8")
w.Write([]byte(`<? xml version = ” 1. 。” encoding = ” utf -
8 ” 节><Message>Hello World</Message >、`))
default:
w.Header().Set("Content-Type","text/plain;charset=utf-8")
w.Write([]byte("hello World"))
}
}
func main(){
http.HandleFunc("/",helloWorld)
http.ListenAndServe(":8000",nil)
}
// $ curl -is http://localhost:8000 -H "Accept:application/json"
// HTTP/1.1 200 OK
// Content-Type: application/json ; charset=utf-8
// Date: Thu, 28 Jan 2021 15:02:20 GMT
// Content-Length: 25
// {"message":"Hello World"}
- 使用-H来发送报头
响应不同类型的请求
HTTP服务器通常也需要能够响应不同类型的请求。客户端可发出的请求类型是HTTP规范中定义的,包括GET、POST、PUT和DELETE
package main
import (
"net/http"
)
func hello(w http.ResponseWriter,r *http.Request){
if r.URL.Path != "/"{
http.NotFound(w,r)
return
}
switch r.Method{
case "GET":
w.Write([]byte("Received a GET"))
case "POST":
w.Write([]byte("Received a POST"))
default:
w.WriteHeader(http.StatusNotImplemented)
w.Write([]byte("error"))
}
}
func main(){
http.HandleFunc("/",hello)
http.ListenAndServe(":8000",nil)
}
// $ curl -is http://127.0.0.1:8000 -X POST
// HTTP/1.1 200 OK
// Date: Thu, 28 Jan 2021 15:18:24 GMT
// Content-Length: 15
// Content-Type: text/plain; charset=utf-8
// Received a POST
// Administrator@PC-202101161235 MINGW64 ~
// $ curl -is http://127.0.0.1:8000 -X GET
// HTTP/1.1 200 OK
// Date: Thu, 28 Jan 2021 15:18:34 GMT
// Content-Length: 14
// Content-Type: text/plain; charset=utf-8
// Received a GET
- 可以使用-X选项来指定请求的类型
获取GET和POST请求中的数据
HTTP客户端可在HTTP请求中向HTTP服务器发送数据,这样的典型实例包含以下几点:
- 提交表单
- 设置有关要返回的数据的选项
- 通过API管理数据
读取URL中GET请求的数据
func queryParams(w http.ResponseWriter,r *http.Request){
for k,v := range r.URL.Query(){
fmt.Printf("%s : %s \n",k,v)
}
}
在POST请求中,数据通常是在请求体中发送的。要读取并使用这些数据,可像下面这样做
func queryParams(w http.ResponseWriter,r *http.Request){
reqBody,err := ioutil.ReadAll(r.Body)
if err != nil{
log.Fatal(err)
}
fmt.Printf("%s",reqBody)
}
下面是一个实例
package main
import(
"net/http"
"log"
"io/ioutil"
"fmt"
)
func hello(w http.ResponseWriter,r *http.Request){
if r.URL.Path !="/"{
http.NotFound(w,r)
return
}
switch r.Method{
case "GET":
for k,v := range r.URL.Query(){
w.Write([]byte(string(k)+":"+string(v[0])))
w.Write([]byte("\nGET"))
}
case "POST":
reqBody,err := ioutil.ReadAll(r.Body)
if err != nil {
log.Fatal(err)
}
w.Write([]byte(reqBody))
w.Write([]byte("\nPOST"))
}
}
func main(){
http.HandleFunc("/",hello)
http.ListenAndServe(":8000",nil)
}
运行结果:
//发送GET
$ curl -is http://127.0.0.1:8000/?foot=siqu -X GET
HTTP/1.1 200 OK
Date: Thu, 28 Jan 2021 15:45:28 GMT
Content-Length: 13
Content-Type: text/plain; charset=utf-8
foot:siqu
GET
//发送POST
$ curl -is http://127.0.0.1:8000/?foot=siqu -X POST -d "some data to send"
HTTP/1.1 200 OK
Date: Thu, 28 Jan 2021 15:58:25 GMT
Content-Length: 22
Content-Type: text/plain; charset=utf-8
some data to send
POST
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容