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数据
相关推荐
代码游侠40 分钟前
应用——智能配电箱监控系统
linux·服务器·数据库·笔记·算法·sqlite
Tisfy1 小时前
网站访问耗时优化 - 从数十秒到几百毫秒的“零成本”优化过程
服务器·开发语言·性能优化·php·网站·建站
2501_933513041 小时前
Linux下载离线rpm和依赖包的方法
linux·运维·服务器
ps酷教程1 小时前
HttpPostRequestDecoder源码浅析
java·http·netty
闲人编程1 小时前
消息通知系统实现:构建高可用、可扩展的企业级通知服务
java·服务器·网络·python·消息队列·异步处理·分发器
XiaoHu02071 小时前
Linux多线程(详细全解)
linux·运维·服务器·开发语言·c++·git
Xの哲學1 小时前
Linux Platform驱动深度剖析: 从设计思想到实战解析
linux·服务器·网络·算法·边缘计算
gaize12131 小时前
服务器怎么选择与配置才能满足企业需求?
运维·服务器·架构
福大大架构师每日一题2 小时前
2026年1月TIOBE编程语言排行榜,Go语言排名第16,Rust语言排名13。C# 当选 2025 年度编程语言。
golang·rust·c#
寻星探路3 小时前
【Python 全栈测开之路】Python 基础语法精讲(一):常量、变量与运算符
java·开发语言·c++·python·http·ai·c#