Golang:使用net/http实现一个简易的http服务器

文档

1、实现一个简易的服务端

go 复制代码
package main

import (
    "fmt"
    "net/http"
)

// 请求处理函数
func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("hello world!"))
}

func main() {

    // 路由
    http.HandleFunc("/", helloHandler)

    // 启动服务
    fmt.Printf("http server starting at http://127.0.0.1:9090\n")

    err := http.ListenAndServe(":9090", nil)

    if err != nil {
        fmt.Printf("http server failed, err:%v\n", err)
        return
    }
}

请求示例

bash 复制代码
$ curl http://127.0.0.1:9090/
hello world!

示例

2、实现一个类似 https://httpbin.org/的服务,返回请求的信息

go 复制代码
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "strings"
)

type Result struct {
    Args    map[string]string      `json:"args"`
    Headers map[string]string      `json:"headers"`
    Form    map[string]string      `json:"form"`
    Json    map[string]interface{} `json:"json"`
    Method  string                 `json:"method"`
    Data    string                 `json:"data"`
    Url     string                 `json:"url"`
    Origin  string                 `json:"origin"`
}

func echoHandler(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()

    ret := &Result{}
    ret.Method = r.Method
    ret.Origin = r.RemoteAddr

    // 完整url
    scheme := "http://"
    if r.TLS != nil {
        scheme = "https://"
    }

    ret.Url = strings.Join([]string{scheme, r.Host, r.RequestURI}, "")

    // raw data
    data, _ := io.ReadAll(r.Body)
    ret.Data = string(data)

    // form
    // r.ParseForm()
    // ret.Form = make(map[string]string)
    // for key, _ := range r.PostForm {
    //  ret.Form[key] = r.PostForm.Get(key)
    // }

    // 通过raw data解析
    ret.Form = make(map[string]string)
    form, err := url.ParseQuery(string(data))
    if err != nil {
        for key, _ := range form {
            ret.Form[key] = form.Get(key)
        }
    }

    // json
    ret.Json = make(map[string]interface{})
    json.Unmarshal(data, &ret.Json)

    // args
    ret.Args = make(map[string]string)
    for key, _ := range r.URL.Query() {
        ret.Args[key] = r.URL.Query().Get(key)
    }

    // header
    ret.Headers = make(map[string]string)

    for key, _ := range r.Header {
        ret.Headers[key] = r.Header.Get(key)
    }

    body, _ := json.Marshal(ret)
    w.Write(body)
}

func main() {

    // 路由
    http.HandleFunc("/", echoHandler)

    // 启动服务
    fmt.Printf("http server starting at http://127.0.0.1:9090\n")

    err := http.ListenAndServe(":9090", nil)

    if err != nil {
        fmt.Printf("http server failed, err:%v\n", err)
        return
    }
}

注意:由于请求体只能读取一次,所以form和rawData只能取到一个

通过客户端发起请求

go 复制代码
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
)

func main() {
    targetUrl := "http://127.0.0.1:9090"

    // url args
    u, _ := url.ParseRequestURI(targetUrl)

    params := url.Values{}
    params.Set("name", "Tom")
    params.Set("age", "18")

    u.RawQuery = params.Encode() // URL encode

    // json
    data := make(map[string]interface{})
    data["name"] = "Tom"
    data["age"] = 12

    resqdata, _ := json.Marshal(data)

    client := &http.Client{}
    req, _ := http.NewRequest("POST", u.String(), bytes.NewReader(resqdata))

    // header
    req.Header.Add("X-Token", "token")
    req.Header.Add("Content-Type", "application/json")

    resp, _ := client.Do(req)
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))

}

返回结果

json 复制代码
{
    "args": {
        "age": "18",
        "name": "Tom"
    },
    "headers": {
        "Accept-Encoding": "gzip",
        "Content-Length": "23",
        "Content-Type": "application/json",
        "User-Agent": "Go-http-client/1.1",
        "X-Token": "token"
    },
    "form": {},
    "json": {
        "age": 12,
        "name": "Tom"
    },
    "method": "POST",
    "data": "{\"age\":12,\"name\":\"Tom\"}",
    "url": "http://127.0.0.1:9090/?age=18&name=Tom",
    "origin": "127.0.0.1:62103"
}

可以看到,我们的服务端可以正确获取到请求的参数信息和json请求体,以及请求头部信息

【参考 】

  1. 深入探索Go语言net/http包:构建高性能的Web服务
  2. Golang:发起http请求-GET带参数、POST发送Form和JSON数据
相关推荐
leisoo809744 分钟前
100GBA股股票数据怎么存ClickHouseRedisMySQLJSON完整对比
大数据·linux·服务器·开发语言·python
码上上班2 小时前
tengine知识点
linux·服务器·centos
雾时之林5 小时前
Linux--软件管理、源码包安装
linux·服务器·数据库
Sylvia33.8 小时前
从轮询到推送:足球数据API架构演进与火星数据技术拆解
java·服务器·网络·python·websocket·架构
RisunJan9 小时前
Linux命令-sshd(SSH 服务器守护进程)
linux·服务器·ssh
圣殿骑士-Khtangc11 小时前
Go-Map面试核心考点从哈希冲突到并发安全的完整解析
面试·golang·哈希算法
worxfr11 小时前
Go 并发控制:从 Channel 方向约束到实战模式
开发语言·后端·golang
程序员老陆11 小时前
说一说FFmpeg6在Linux平台的编译
linux·运维·服务器·ffmpeg
玫幽倩11 小时前
2026黄河流域公安院校-电子物证单项赛(程序逆向分析+服务器取证)
运维·服务器·python·电子取证·逆向·程序分析·服务器取证
xcLeigh11 小时前
Go入门:短变量声明的陷阱与最佳实践
java·redis·golang·教程·变量