云原生之旅 - 1)Golang 入门 简单 HTTP Server

打印 上一主题 下一主题

主题 1014|帖子 1014|积分 3042

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

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.   1 package main
  2.   2
  3.   3 import (
  4.   4     "encoding/json"
  5.   5     "fmt"
  6.   6     "log"
  7.   7     "net/http"
  8.   8 )
  9.   9
  10. 10 type Pizza struct {
  11. 11     ID    int    `json:"id"`
  12. 12     Name  string `json:"name"`
  13. 13     Price int    `json:"price"`
  14. 14 }
  15. 15
  16. 16 type Pizzas []Pizza
  17. 17
  18. 18 func (ps Pizzas) FindByID(ID int) (Pizza, error) {
  19. 19     for _, pizza := range ps {
  20. 20         if pizza.ID == ID {
  21. 21             return pizza, nil
  22. 22         }
  23. 23     }
  24. 24
  25. 25     return Pizza{}, fmt.Errorf("couldn't find pizza with ID: %d", ID)
  26. 26 }
  27. 27
  28. 28 type Order struct {
  29. 29     PizzaID  int `json:"pizza_id"`
  30. 30     Quantity int `json:"quantity"`
  31. 31     Total    int `json:"total"`
  32. 32 }
  33. 33
  34. 34 type Orders []Order
  35. 35
  36. 36 type pizzasHandler struct {
  37. 37     pizzas *Pizzas
  38. 38 }
  39. 39
  40. 40 func (ph pizzasHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  41. 41     w.Header().Set("Content-Type", "application/json")
  42. 42
  43. 43     switch r.Method {
  44. 44     case http.MethodGet:
  45. 45         if len(*ph.pizzas) == 0 {
  46. 46             http.Error(w, "Error: No pizzas found", http.StatusNotFound)
  47. 47             return
  48. 48         }
  49. 49
  50. 50         json.NewEncoder(w).Encode(ph.pizzas)
  51. 51     default:
  52. 52         http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  53. 53     }
  54. 54 }
  55. 55
  56. 56 type ordersHandler struct {
  57. 57     pizzas *Pizzas
  58. 58     orders *Orders
  59. 59 }
  60. 60
  61. 61 func (oh ordersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  62. 62     w.Header().Set("Content-Type", "application/json")
  63. 63
  64. 64     switch r.Method {
  65. 65     case http.MethodPost:
  66. 66         var o Order
  67. 67
  68. 68         if len(*oh.pizzas) == 0 {
  69. 69             http.Error(w, "Error: No pizzas found", http.StatusNotFound)
  70. 70             return
  71. 71         }
  72. 72
  73. 73         err := json.NewDecoder(r.Body).Decode(&o)
  74. 74         if err != nil {
  75. 75             http.Error(w, "Can't decode body", http.StatusBadRequest)
  76. 76             return
  77. 77         }
  78. 78
  79. 79         p, err := oh.pizzas.FindByID(o.PizzaID)
  80. 80         if err != nil {
  81. 81             http.Error(w, fmt.Sprintf("Error: %s", err), http.StatusBadRequest)
  82. 82             return
  83. 83         }
  84. 84
  85. 85         o.Total = p.Price * o.Quantity
  86. 86         *oh.orders = append(*oh.orders, o)
  87. 87         json.NewEncoder(w).Encode(o)
  88. 88     case http.MethodGet:
  89. 89         json.NewEncoder(w).Encode(oh.orders)
  90. 90     default:
  91. 91         http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  92. 92     }
  93. 93 }
  94. 94
  95. 95 func main() {
  96. 96     var orders Orders
  97. 97     pizzas := Pizzas{
  98. 98         Pizza{
  99. 99             ID:    1,
  100. 100             Name:  "Veggie",
  101. 101             Price: 12,
  102. 102         },
  103. 103         Pizza{
  104. 104             ID:    2,
  105. 105             Name:  "Cheese",
  106. 106             Price: 11,
  107. 107         },
  108. 108         Pizza{
  109. 109             ID:    3,
  110. 110             Name:  "Meat",
  111. 111             Price: 10,
  112. 112         },
  113. 113     }
  114. 114
  115. 115     mux := http.NewServeMux()
  116. 116     mux.Handle("/pizzas", pizzasHandler{&pizzas})
  117. 117     mux.Handle("/orders", ordersHandler{&pizzas, &orders})
  118. 118
  119. 119     log.Fatal(http.ListenAndServe(":8080", mux))
  120. 120 }
复制代码
pizzas 和 orders 数据都保留在内存中,为了尽可能简单,没有任何数据存储持久化,如果需要,我可以开设另一篇来讲 gorm 之类的,也是现学的 :)
也不检查请求的header,客户端发的data body
Source code
 
运行

本地启动 
  1. go run main.go
复制代码
### https://www.cnblogs.com/wade-xu/p/16705918.html ###
 
测试

调用 get all pizzas 接口

 
 
 
 
 
 
 
 
 
 
创建一个 order 订4个 Veggie pizzas
  1. curl -X POST localhost:8080/orders -d '{"pizza_id":1,"quantity":4}' | jq
复制代码

 
 
 
 
 
再创建一个Order 订2个 Cheese pizzas
  1. curl -X POST localhost:8080/orders -d '{"pizza_id":2,"quantity":2}' | jq
  2. {
  3.   "pizza_id": 2,
  4.   "quantity": 2,
  5.   "total": 22
  6. }
复制代码
 
最后 Get orders 看下
 
Simple HTTP server works well.
### https://www.cnblogs.com/wade-xu/p/16705918.html ###
 
感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以打赏和推荐,您的鼓励是我创作的动力。
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天津储鑫盛钢材现货供应商

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表