马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
前言
本人最近几年一直在学习并且实践云原生,也从测试转型到DevOps,公司的所有服务也从数据中心搬到云端,回顾过去几年学到的知识,觉得是时候总结一下了,所以准备以云原生为题材写下这一过程中所有学到的知识点,希望对大家有所帮助。
在我带你开始云原生之旅前,需要入门一下golang,没办法,谁让它是云原生领域里正红的发紫的“角儿,从最底层的 containerd,到编排层的 Kubernetes,再到如今正红的发紫的 Istio,随便拿出一个来都是golang写的。我相信你学了Golang之后,会发现它非常好用,library丰富,部署简单,容易上手,咱也不想成为资深开发,但我们自动化,写工具之类的还是需要掌握一门语言的,我反正已经放弃其它学过的语言了。
本篇文章讲述如何构建一个简单的HTTP服务器,Golang的标准库net/http 让这一切变得很容易,仅适用于golang新手(已了解过Golang语言特性)。
关键词:Golang,入门,HTTP server,DevOps,云原生,Golang 例子
Learning By Example
让我们用Pizza餐厅点单作为例子,定义 Pizza 餐厅 API 3个endpoints 如下:
- Get 请求 - List all pizzas: /pizzas
- POST 请求 - Make a pizza order: /orders
- Get 请求 - List all orders: /orders
代码如下:- 1 package main
- 2
- 3 import (
- 4 "encoding/json"
- 5 "fmt"
- 6 "log"
- 7 "net/http"
- 8 )
- 9
- 10 type Pizza struct {
- 11 ID int `json:"id"`
- 12 Name string `json:"name"`
- 13 Price int `json:"price"`
- 14 }
- 15
- 16 type Pizzas []Pizza
- 17
- 18 func (ps Pizzas) FindByID(ID int) (Pizza, error) {
- 19 for _, pizza := range ps {
- 20 if pizza.ID == ID {
- 21 return pizza, nil
- 22 }
- 23 }
- 24
- 25 return Pizza{}, fmt.Errorf("couldn't find pizza with ID: %d", ID)
- 26 }
- 27
- 28 type Order struct {
- 29 PizzaID int `json:"pizza_id"`
- 30 Quantity int `json:"quantity"`
- 31 Total int `json:"total"`
- 32 }
- 33
- 34 type Orders []Order
- 35
- 36 type pizzasHandler struct {
- 37 pizzas *Pizzas
- 38 }
- 39
- 40 func (ph pizzasHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- 41 w.Header().Set("Content-Type", "application/json")
- 42
- 43 switch r.Method {
- 44 case http.MethodGet:
- 45 if len(*ph.pizzas) == 0 {
- 46 http.Error(w, "Error: No pizzas found", http.StatusNotFound)
- 47 return
- 48 }
- 49
- 50 json.NewEncoder(w).Encode(ph.pizzas)
- 51 default:
- 52 http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
- 53 }
- 54 }
- 55
- 56 type ordersHandler struct {
- 57 pizzas *Pizzas
- 58 orders *Orders
- 59 }
- 60
- 61 func (oh ordersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- 62 w.Header().Set("Content-Type", "application/json")
- 63
- 64 switch r.Method {
- 65 case http.MethodPost:
- 66 var o Order
- 67
- 68 if len(*oh.pizzas) == 0 {
- 69 http.Error(w, "Error: No pizzas found", http.StatusNotFound)
- 70 return
- 71 }
- 72
- 73 err := json.NewDecoder(r.Body).Decode(&o)
- 74 if err != nil {
- 75 http.Error(w, "Can't decode body", http.StatusBadRequest)
- 76 return
- 77 }
- 78
- 79 p, err := oh.pizzas.FindByID(o.PizzaID)
- 80 if err != nil {
- 81 http.Error(w, fmt.Sprintf("Error: %s", err), http.StatusBadRequest)
- 82 return
- 83 }
- 84
- 85 o.Total = p.Price * o.Quantity
- 86 *oh.orders = append(*oh.orders, o)
- 87 json.NewEncoder(w).Encode(o)
- 88 case http.MethodGet:
- 89 json.NewEncoder(w).Encode(oh.orders)
- 90 default:
- 91 http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
- 92 }
- 93 }
- 94
- 95 func main() {
- 96 var orders Orders
- 97 pizzas := Pizzas{
- 98 Pizza{
- 99 ID: 1,
- 100 Name: "Veggie",
- 101 Price: 12,
- 102 },
- 103 Pizza{
- 104 ID: 2,
- 105 Name: "Cheese",
- 106 Price: 11,
- 107 },
- 108 Pizza{
- 109 ID: 3,
- 110 Name: "Meat",
- 111 Price: 10,
- 112 },
- 113 }
- 114
- 115 mux := http.NewServeMux()
- 116 mux.Handle("/pizzas", pizzasHandler{&pizzas})
- 117 mux.Handle("/orders", ordersHandler{&pizzas, &orders})
- 118
- 119 log.Fatal(http.ListenAndServe(":8080", mux))
- 120 }
复制代码 pizzas 和 orders 数据都保留在内存中,为了尽可能简单,没有任何数据存储持久化,如果需要,我可以开设另一篇来讲 gorm 之类的,也是现学的 :)
也不检查请求的header,客户端发的data body
Source code
运行
本地启动 ### https://www.cnblogs.com/wade-xu/p/16705918.html ###
测试
调用 get all pizzas 接口

创建一个 order 订4个 Veggie pizzas- curl -X POST localhost:8080/orders -d '{"pizza_id":1,"quantity":4}' | jq
复制代码
再创建一个Order 订2个 Cheese pizzas- curl -X POST localhost:8080/orders -d '{"pizza_id":2,"quantity":2}' | jq
- {
- "pizza_id": 2,
- "quantity": 2,
- "total": 22
- }
复制代码
最后 Get orders 看下
Simple HTTP server works well.
### https://www.cnblogs.com/wade-xu/p/16705918.html ###
感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以打赏和推荐,您的鼓励是我创作的动力。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |