7 Days Go Web Framework Gee from Scratch

7天用Go从零实现Web框架Gee

README - 图1

Content

Day 1 - Static Route

  1. func main() {
  2. r := gee.New()
  3. r.GET("/", func(w http.ResponseWriter, req *http.Request) {
  4. fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path)
  5. })
  6. r.GET("/hello", func(w http.ResponseWriter, req *http.Request) {
  7. for k, v := range req.Header {
  8. fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
  9. }
  10. })
  11. r.Run(":9999")
  12. }

Day 2 - Context Design

  1. func main() {
  2. r := gee.New()
  3. r.GET("/", func(c *gee.Context) {
  4. c.HTML(http.StatusOK, "<h1>Hello Gee</h1>")
  5. })
  6. r.GET("/hello", func(c *gee.Context) {
  7. // expect /hello?name=geektutu
  8. c.String(http.StatusOK, "hello %s, you're at %s\n", c.Query("name"), c.Path)
  9. })
  10. r.POST("/login", func(c *gee.Context) {
  11. c.JSON(http.StatusOK, &map[string]string{
  12. "username": c.PostForm("username"),
  13. "password": c.PostForm("password"),
  14. })
  15. })
  16. r.Run(":9999")
  17. }

Day 3 - Dynamic Route

  1. func main() {
  2. r := gee.New()
  3. r.GET("/", func(c *gee.Context) {
  4. c.HTML(http.StatusOK, "<h1>Hello Gee</h1>")
  5. })
  6. r.GET("/hello", func(c *gee.Context) {
  7. // expect /hello?name=geektutu
  8. c.String(http.StatusOK, "hello %s, you're at %s\n", c.Query("name"), c.Path)
  9. })
  10. r.GET("/hello/:name", func(c *gee.Context) {
  11. // expect /hello/geektutu
  12. c.String(http.StatusOK, "hello %s, you're at %s\n", c.Param("name"), c.Path)
  13. })
  14. r.GET("/assets/*filepath", func(c *gee.Context) {
  15. c.JSON(http.StatusOK, gee.H{"filepath": c.Param("filepath")})
  16. })
  17. r.Run(":9999")
  18. }

Day 4 - Nesting Group Control

  1. func main() {
  2. r := gee.New()
  3. v1 := r.Group("/v1")
  4. {
  5. v1.GET("/", func(c *gee.Context) {
  6. c.HTML(http.StatusOK, "<h1>Hello Gee</h1>")
  7. })
  8. v1.GET("/hello", func(c *gee.Context) {
  9. // expect /hello?name=geektutu
  10. c.String(http.StatusOK, "hello %s, you're at %s\n", c.Query("name"), c.Path)
  11. })
  12. }
  13. v2 := r.Group("/v2")
  14. {
  15. v2.GET("/hello/:name", func(c *gee.Context) {
  16. // expect /hello/geektutu
  17. c.String(http.StatusOK, "hello %s, you're at %s\n", c.Param("name"), c.Path)
  18. })
  19. v2.POST("/login", func(c *gee.Context) {
  20. c.JSON(http.StatusOK, &map[string]string{
  21. "username": c.PostForm("username"),
  22. "password": c.PostForm("password"),
  23. })
  24. })
  25. }
  26. r.Run(":9999")
  27. }

Day 5 - Middleware

  1. func onlyForV2() gee.HandlerFunc {
  2. return func(c *gee.Context) {
  3. // Start timer
  4. t := time.Now()
  5. // if a server error occurred
  6. c.Fail(500, "Internal Server Error")
  7. // Calculate resolution time
  8. log.Printf("[%d] %s in %v for group v2", c.StatusCode, c.Req.RequestURI, time.Since(t))
  9. }
  10. }
  11. func main() {
  12. r := gee.New()
  13. r.Use(gee.Logger()) // global midlleware
  14. r.GET("/", func(c *gee.Context) {
  15. c.HTML(http.StatusOK, "<h1>Hello Gee</h1>")
  16. })
  17. v2 := r.Group("/v2")
  18. v2.Use(onlyForV2()) // v2 group middleware
  19. {
  20. v2.GET("/hello/:name", func(c *gee.Context) {
  21. // expect /hello/geektutu
  22. c.String(http.StatusOK, "hello %s, you're at %s\n", c.Param("name"), c.Path)
  23. })
  24. }
  25. r.Run(":9999")
  26. }

Day 6 - HTML Template

  1. type student struct {
  2. Name string
  3. Age int8
  4. }
  5. func FormatAsDate(t time.Time) string {
  6. year, month, day := t.Date()
  7. return fmt.Sprintf("%d-%02d-%02d", year, month, day)
  8. }
  9. func main() {
  10. r := gee.New()
  11. r.Use(gee.Logger())
  12. r.SetFuncMap(template.FuncMap{
  13. "FormatAsDate": FormatAsDate,
  14. })
  15. r.LoadHTMLGlob("templates/*")
  16. r.Static("/assets", "./static")
  17. stu1 := &student{Name: "Geektutu", Age: 20}
  18. stu2 := &student{Name: "Jack", Age: 22}
  19. r.GET("/", func(c *gee.Context) {
  20. c.HTML(http.StatusOK, "css.tmpl", nil)
  21. })
  22. r.GET("/students", func(c *gee.Context) {
  23. c.HTML(http.StatusOK, "arr.tmpl", gee.H{
  24. "title": "gee",
  25. "stuArr": [2]*student{stu1, stu2},
  26. })
  27. })
  28. r.GET("/date", func(c *gee.Context) {
  29. c.HTML(http.StatusOK, "custom_func.tmpl", gee.H{
  30. "title": "gee",
  31. "now": time.Date(2019, 8, 17, 0, 0, 0, 0, time.UTC),
  32. })
  33. })
  34. r.Run(":9999")
  35. }

Day 7 - Panic Recover

  1. func main() {
  2. r := gee.Default()
  3. r.GET("/", func(c *gee.Context) {
  4. c.String(http.StatusOK, "Hello Geektutu\n")
  5. })
  6. // index out of range for testing Recovery()
  7. r.GET("/panic", func(c *gee.Context) {
  8. names := []string{"geektutu"}
  9. c.String(http.StatusOK, names[100])
  10. })
  11. r.Run(":9999")
  12. }