go语言web框架:Echo超详细一文搞透

一、概述

1、官网

官方网站:https://echo.labstack.com
GitHub资源库:https://github.com/labstack/echo
文档:https://echo.labstack.com/docs
社区论坛:https://github.com/labstack/echo/discussions

2、安装echo

# 指定国内包源地址
go env -w GOPROXY=https://goproxy.cn
# 下载echo包
go get github.com/labstack/echo/v4

二、基本使用

1、基本语法

创建server.go

package main

import (
	"net/http"
	"github.com/labstack/echo/v4"
	"os"
	"io"
)

func main() {
	e := echo.New()
	// 路由
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.GET("/show", show)
	e.GET("/users/:id", getUser)
	e.POST("/users", saveUser)
	e.PUT("/users/:id", updateUser)
	e.DELETE("/users/:id", deleteUser)
	// 端口
	e.Logger.Fatal(e.Start(":8080"))
}

//e.GET("/show", show)
func show(c echo.Context) error {
	// http://localhost:8080/show?team=x-men&member=wolverine 获取team和member参数
	team := c.QueryParam("team")
	member := c.QueryParam("member")
	return c.String(http.StatusOK, "team:" + team + ", member:" + member)
}

// e.GET("/users/:id", getUser)
func getUser(c echo.Context) error {
	//  http://localhost:8080/users/zhangsan 获取path参数
	id := c.Param("id")
  return c.String(http.StatusOK, id)
}

// e.POST("/users", saveUser)
func saveUser(c echo.Context) error {
	// 获取Form表单参数
	name := c.FormValue("name")
	email := c.FormValue("email")
	// 获取文件
	avatar, err := c.FormFile("avatar")
  	if err != nil {
 		return err
 	}
 
 	// Source
 	src, err := avatar.Open()
 	if err != nil {
 		return err
 	}
 	defer src.Close()
 
 	// Destination
 	dst, err := os.Create(avatar.Filename)
 	if err != nil {
 		return err
 	}
 	defer dst.Close()
 
 	// Copy 文件下载到项目根路径
 	if _, err = io.Copy(dst, src); err != nil {
  		return err
  	}
	return c.String(http.StatusOK, "name:" + name + ", email:" + email)
}


type User struct {
	Name  string `json:"name" xml:"name" form:"name" query:"name"`
	Email string `json:"email" xml:"email" form:"email" query:"email"`
}
// e.PUT("/users/:id", updateUser)
func updateUser(c echo.Context) error {
	u := new(User)
	// 根据内容类型请求头将json、xml、表单或查询参数,自动绑定到Go结构体中。
	if err := c.Bind(u); err != nil {
		return err
	}
	return c.JSON(http.StatusCreated, u)
	// or
	// return c.XML(http.StatusCreated, u)
}

// e.DELETE("/users/:id", deleteUser)
func deleteUser(c echo.Context) error {
	//  http://localhost:8080/users/zhangsan 获取path参数
	id := c.Param("id")
  return c.String(http.StatusOK, id)
}

执行:go run server.go,端口8080

2、使用Bind对参数进行绑定

package main

import (
	"github.com/labstack/echo/v4"
	"net/http"
)

/*
可以绑定的类型:
query-查询参数
param-路径参数(也称为路由)
header-标题参数
json-请求body
xml-请求body
form-表单数据。值取自查询和请求正文。使用Go标准库格式解析。
*/
type User struct {
	Name  string `json:"name" form:"name" query:"name"`
	Email string `json:"email" form:"email" query:"email"`
}

type UserDTO struct {
	Name    string
	Email   string
	IsAdmin bool
}

func main() {
	e := echo.New()
	// 路由
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.GET("/show", func(c echo.Context) error {
		// http://localhost:8080/show?id=123
		// 查询参数的id会绑定到user的ID
		var user User
		err := c.Bind(&user)
		if err != nil {
			return c.String(http.StatusBadRequest, "bad request")
		}
		return c.JSON(http.StatusCreated, user)
	})

	e.POST("/users", func(c echo.Context) (err error) {
		// 绑定user
		u := new(User)
		if err := c.Bind(u); err != nil {
			return c.String(http.StatusBadRequest, "bad request")
		}

		// 为了安全起见,加载到单独的结构体中:UserDTO
		user := UserDTO{
			Name:    u.Name,
			Email:   u.Email,
			IsAdmin: false, // 避免公开不绑定的字段
		}

		// 使用user执行其他逻辑

		return c.JSON(http.StatusOK, user)
	})
	e.Logger.Fatal(e.Start(":8080"))
}

3、响应处理

package main

import (
	"github.com/labstack/echo/v4"
	"net/http"
	"os"
)

// User
type User struct {
	Name  string `json:"name" xml:"name"`
	Email string `json:"email" xml:"email"`
}

func main() {
	e := echo.New()
	// 响应字符串
	e.GET("/string", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	// 响应html
	e.GET("/html", func(c echo.Context) error {
		return c.HTML(http.StatusOK, "<strong>Hello, World!</strong>")
	})
	// 响应json
	e.GET("/json1", func(c echo.Context) error {
		u := &User{
			Name:  "张三",
			Email: "1111@qq.com",
		}
		return c.JSON(http.StatusOK, u)
	})
	// 响应 格式化之后的json,传一个缩进符
	e.GET("/json2", func(c echo.Context) error {
		u := &User{
			Name:  "张三",
			Email: "1111@qq.com",
		}
		return c.JSON(http.StatusOK, c.JSONPretty(http.StatusOK, u, "  "))
	})
	// 响应xml
	e.GET("/xml1", func(c echo.Context) error {
		u := &User{
			Name:  "张三",
			Email: "1111@qq.com",
		}
		return c.XML(http.StatusOK, u)
	})
	// 格式化 响应xml
	e.GET("/xml2", func(c echo.Context) error {
		u := &User{
			Name:  "张三",
			Email: "1111@qq.com",
		}
		return c.XMLPretty(http.StatusOK, u, "  ")
	})
	// 响应文件
	e.GET("/file1", func(c echo.Context) error {
		return c.File("C:\\Users\\Admin\\Pictures\\netty.png")
	})
	e.GET("/file2", func(c echo.Context) error {
		return c.File("D:\\goland-2024.1.4.exe")
	})
	// 响应文件,附带文件名
	e.GET("/file3", func(c echo.Context) error {
		return c.Attachment("D:\\goland-2024.1.4.exe", "goland.exe")
	})
	// 响应流
	e.GET("/stream", func(c echo.Context) error {
		f, err := os.Open("C:\\Users\\Admin\\Pictures\\netty.png")
		if err != nil {
			return err
		}
		return c.Stream(http.StatusOK, "image/png", f)
	})
	// 响应空
	e.GET("/none", func(c echo.Context) error {
		return c.NoContent(http.StatusOK)
	})
	// 重定向
	e.GET("/redirect", func(c echo.Context) error {
		return c.Redirect(http.StatusMovedPermanently, "/string")
	})

	e.Logger.Fatal(e.Start(":8080"))
}

指定响应内容

type Map map[string]interface{}

func Fail(c echo.Context, code int, message string) error {
	return c.JSON(200, Map{
		"code":    code,
		"message": message,
	})
}

func FailWithData(c echo.Context, code int, message string, data interface{}) error {
	return c.JSON(200, Map{
		"code":    code,
		"message": message,
		"data":    data,
	})
}

func Success(c echo.Context, data interface{}) error {
	return c.JSON(200, Map{
		"code":    1,
		"message": "success",
		"data":    data,
	})
}

4、路由分组

package main

import (
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	"net/http"
)

func main() {
	e := echo.New()

	// 路由分组
	admin := e.Group("/admin")
	admin.GET("/test1", func(c echo.Context) error {
		return c.String(http.StatusOK, "admin test1")
	})
	admin.GET("/test2", func(c echo.Context) error {
		return c.String(http.StatusOK, "admin test2")
	})

	// 第二个路由组
	user := e.Group("/user")
	user.GET("/test1", func(c echo.Context) error {
		return c.String(http.StatusOK, "user test1")
	})

	e.Logger.Fatal(e.Start(":8080"))
}

5、静态文件服务

package main

import (
	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()

	// 指定路径,该路径下的文件会提供文件服务(参数一:前缀,参数二:本地路径)
	// 访问localhost:8080/static/xxx.png 即可访问文件
	e.Static("/static", "D:\\")

	// 静态页面
	e.File("/", "public/index.html")
	
	// 指定文件
	e.File("/favicon.ico", "images/favicon.ico")

	e.Logger.Fatal(e.Start(":8080"))
}

6、Middleware:基本身份认证

package main

import (
	"github.com/labstack/echo/v4"
	"net/http"
)

type Map map[string]interface{}

func main() {
	e := echo.New()

	// 路由分组,并且该路由分组下都需要验证
	admin := e.Group("/admin") // 或者直接admin := e.Group("/admin", Auth)
	admin.Use(Auth)

	admin.GET("/test1", func(c echo.Context) error {
		return c.String(http.StatusOK, "admin test1")
	})
	admin.GET("/test2", func(c echo.Context) error {
		return c.String(http.StatusOK, "admin test2")
	})

	// 第二个路由组
	user := e.Group("/user")
	user.GET("/test1", func(c echo.Context) error {
		return c.String(http.StatusOK, "user test1")
	})

	e.Logger.Fatal(e.Start(":8080"))
}

func Auth(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {

		// 校验token
		if !checkToken(c) {
			return c.JSON(200, Map{
				"code":    401,
				"message": "您的登录信息已失效,请重新登录后再试。",
			})
		}

		return next(c)
	}
}

func GetToken(c echo.Context) string {
	token := c.Request().Header.Get("H-Token")
	if len(token) > 0 {
		return token
	}
	return c.QueryParam("H-Token")
}

func checkToken(c echo.Context) bool {
	token := GetToken(c)
	// 从redis或者其他地方校验token的有效性

	if token == "user" {
		return true
	}
	return false
}

7、使用session

package main

import (
	"errors"
	"fmt"
	"github.com/gorilla/sessions"
	"github.com/labstack/echo-contrib/session"
	"github.com/labstack/echo/v4"
	"log"
	"net/http"
)

func main() {
	e := echo.New()
	e.Use(session.Middleware(sessions.NewCookieStore([]byte("secret"))))

	e.GET("/create-session", func(c echo.Context) error {
		sess, err := session.Get("session", c)
		if err != nil {
			return err
		}
		sess.Options = &sessions.Options{
			Path:     "/",
			MaxAge:   86400 * 7,
			HttpOnly: true,
		}
		sess.Values["foo"] = "bar"
		if err := sess.Save(c.Request(), c.Response()); err != nil {
			return err
		}
		return c.NoContent(http.StatusOK)
	})

	e.GET("/read-session", func(c echo.Context) error {
		sess, err := session.Get("session", c)
		if err != nil {
			return err
		}
		return c.String(http.StatusOK, fmt.Sprintf("foo=%v\n", sess.Values["foo"]))
	})

	if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
		log.Fatal(err)
	}
}

相关推荐

  1. go语言web框架Echo详细

    2024-07-19 16:36:05       20 阅读
  2. 懂C语言

    2024-07-19 16:36:05       25 阅读
  3. goweb开发框架gin(

    2024-07-19 16:36:05       28 阅读
  4. 《Python基础语言 》— Echo

    2024-07-19 16:36:05       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 16:36:05       101 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 16:36:05       109 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 16:36:05       87 阅读
  4. Python语言-面向对象

    2024-07-19 16:36:05       96 阅读

热门阅读

  1. OJ-0718

    2024-07-19 16:36:05       22 阅读
  2. 【Python中的垃圾回收机制是什么】

    2024-07-19 16:36:05       23 阅读
  3. 基于深度学习的人脸表情识别系统

    2024-07-19 16:36:05       26 阅读
  4. Rancher

    Rancher

    2024-07-19 16:36:05      24 阅读
  5. 5、在共享内存无指针编程:句柄HANDLE转换为指针

    2024-07-19 16:36:05       25 阅读
  6. 探索单片机的光耦:定义、作用与应用

    2024-07-19 16:36:05       25 阅读
  7. C 语言实例 - 使用引用循环替换数值

    2024-07-19 16:36:05       27 阅读
  8. 数据结构---数组

    2024-07-19 16:36:05       23 阅读
  9. 【windows】网络信息相关命令

    2024-07-19 16:36:05       23 阅读
  10. python3.11SSL: SSLV3_ALERT_HANDSHAKE_FAILURE

    2024-07-19 16:36:05       24 阅读