前言
本人最近几年一直在学习并且实践云原生,也从测试转型到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
运行
本地启动
go run main.go
### 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 ###
感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以打赏和推荐,您的鼓励是我创作的动力。
Learning by Doing
来源:https://www.cnblogs.com/wade-xu/p/16705918.html
本站部分图文来源于网络,如有侵权请联系删除。