golang构建Web应用的微框架插件WebGo的使用

Golang构建Web应用的微框架插件WebGo的使用

WebGo是一个用于构建Go Web应用程序的简约路由器(服务器端),没有第三方依赖。WebGo将始终与Go标准库兼容,HTTP处理程序具有与http.HandlerFunc相同的签名。

webgo gopher

路由器

WebGo有一个简单的线性路径匹配路由器,支持定义以下模式的URI:

  1. /api/users - 没有动态值的URI
  2. /api/users/:userID
    • 带有命名参数的URI,userID
    • 如果TrailingSlash设置为true,它将接受以’/'结尾的URI
  3. /api/users/:misc*
    • 命名URI参数misc,带有通配符后缀’*’
    • 这匹配/api/users之后的所有内容。例如/api/users/a/b/c/d

当有多个处理程序匹配相同的URI时,只有第一个出现的处理程序会处理请求。

func helloWorld(w http.ResponseWriter, r *http.Request) {
    // WebGo context
    wctx := webgo.Context(r)
    // URI参数,map[string]string
    params := wctx.Params()
    // route, 执行此请求的webgo.Route
    route := wctx.Route
    webgo.R200(
        w,
        fmt.Sprintf(
            "Route name: '%s', params: '%s'",
            route.Name,
            params,
        ),
    )
}

处理程序链

处理程序链允许您为给定路由执行多个处理程序。如果设置FallThroughPostResponsetrue,可以在处理程序已向HTTP请求写入响应后配置链的执行。

中间件

WebGo中间件允许您用中间件包装所有路由,这与处理程序链不同。路由器公开了方法UseUseOnSpecialHandlers来向路由器添加中间件。

NotFound和NotImplemented被视为"特殊"处理程序。特殊处理程序中的webgo.Context(r)将返回nil

func main() {
    router.Use(accesslog.AccessLog, cors.CORS(nil))
    router.Use(<more middleware>)
}

错误处理

Webgo上下文有2种方法来设置和获取请求上下文中的错误。它使Webgo能够实现一个中间件,您可以在其中处理HTTP处理程序中返回的错误。

辅助函数

WebGo提供了一些辅助函数。使用SendSendResponse(其他Rxxx响应函数)时,响应将包装在WebGo的响应结构体中,并序列化为JSON。

{
  "data": "<any valid JSON payload>",
  "status": "<HTTP status code, of type integer>"
}

使用SendError时,响应将包装在WebGo的错误响应结构体中,并序列化为JSON。

{
  "errors": "<any valid JSON payload>",
  "status": "<HTTP status code, of type integer>"
}

HTTPS就绪

通过提供key和cert文件,可以轻松启动HTTPS服务器。您也可以同时运行HTTP和HTTPS服务器。

启动HTTPS服务器:

cfg := &webgo.Config{
    Port: "80",
    HTTPSPort: "443",
    CertFile: "/path/to/certfile",
    KeyFile: "/path/to/keyfile",
}
router := webgo.NewRouter(cfg, routes()...)
router.StartHTTPS()

同时启动HTTP和HTTPS服务器:

cfg := &webgo.Config{
    Port: "80",
    HTTPSPort: "443",
    CertFile: "/path/to/certfile",
    KeyFile: "/path/to/keyfile",
}

router := webgo.NewRouter(cfg, routes()...)
go router.StartHTTPS()
router.Start()

优雅关闭

优雅关闭允许您关闭服务器而不影响任何实时连接/连接到服务器的客户端。启动关闭后,任何新的连接请求都将被忽略。

func main() {
    osSig := make(chan os.Signal, 5)

    cfg := &webgo.Config{
        Host:            "",
        Port:            "8080",
        ReadTimeout:     15 * time.Second,
        WriteTimeout:    60 * time.Second,
        ShutdownTimeout: 15 * time.Second,
    }
    router := webgo.NewRouter(cfg, routes()...)

    go func() {
        <-osSig
        // 启动HTTP服务器关闭
        err := router.Shutdown()
        if err != nil {
            fmt.Println(err)
            os.Exit(1)
        } else {
            fmt.Println("shutdown complete")
            os.Exit(0)
        }
    }()

    go func(){
        time.Sleep(time.Second*15)
        signal.Notify(osSig, os.Interrupt, syscall.SIGTERM)
    }()

    router.Start()
}

完整示例

以下是一个使用WebGo构建简单Web应用的完整示例:

package main

import (
	"fmt"
	"net/http"
	"time"
	
	"github.com/naughtygopher/webgo"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	wctx := webgo.Context(r)
	params := wctx.Params()
	route := wctx.Route
	
	webgo.R200(
		w,
		fmt.Sprintf(
			"Route name: '%s', params: '%s'",
			route.Name,
			params,
		),
	)
}

func routes() []*webgo.Route {
	return []*webgo.Route{
		{
			Name:     "hello",               // 路由名称
			Method:   http.MethodGet,        // 请求方法
			Pattern:  "/hello/:name",        // 路由模式
			Handlers: []http.HandlerFunc{helloWorld}, // 处理函数
		},
	}
}

func main() {
	cfg := &webgo.Config{
		Host:            "",
		Port:            "8080",
		ReadTimeout:     15 * time.Second,
		WriteTimeout:    60 * time.Second,
		ShutdownTimeout: 15 * time.Second,
	}
	
	router := webgo.NewRouter(cfg, routes()...)
	router.Start()
}

这个示例创建了一个简单的Web服务器,监听8080端口,并提供了一个路由/hello/:name,当访问时会返回路由名称和参数信息。


更多关于golang构建Web应用的微框架插件WebGo的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang构建Web应用的微框架插件WebGo的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


WebGo: 轻量级Golang Web微框架使用指南

WebGo是一个轻量级的Golang Web框架,它提供了构建Web应用所需的核心功能,同时保持了极简的设计理念。下面我将详细介绍WebGo的使用方法,并提供示例代码。

安装WebGo

首先需要安装WebGo包:

go get github.com/bnkamalesh/webgo/v6

基本使用示例

package main

import (
	"fmt"
	"net/http"
	
	"github.com/bnkamalesh/webgo/v6"
)

func hello(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("Hello, World!"))
}

func main() {
	// 定义路由
	routes := []*webgo.Route{
		{
			Name:     "hello",
			Method:   http.MethodGet,
			Pattern:  "/",
			Handlers: []http.HandlerFunc{hello},
		},
	}

	// 创建WebGo配置
	cfg := &webgo.Config{
		Host:         "localhost",
		Port:         "8080",
		ReadTimeout:  10,
		WriteTimeout: 10,
	}

	// 创建路由器
	router := webgo.NewRouter(cfg, routes...)

	// 启动服务器
	webgo.GracefulShutdown(router)
}

核心功能

1. 路由定义

WebGo支持RESTful风格的路由定义:

routes := []*webgo.Route{
	{
		Name:     "get-users",
		Method:   http.MethodGet,
		Pattern:  "/users",
		Handlers: []http.HandlerFunc{getUsers},
	},
	{
		Name:     "get-user",
		Method:   http.MethodGet,
		Pattern:  "/users/:id",
		Handlers: []http.HandlerFunc{getUser},
	},
	{
		Name:     "create-user",
		Method:   http.MethodPost,
		Pattern:  "/users",
		Handlers: []http.HandlerFunc{createUser},
	},
}

2. 路径参数获取

func getUser(w http.ResponseWriter, r *http.Request) {
	params := webgo.Context(r).Params()
	userID := params["id"]
	
	// 查询数据库或其他操作
	fmt.Fprintf(w, "User ID: %s", userID)
}

3. 中间件支持

WebGo支持中间件链:

func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("Request: %s %s\n", r.Method, r.URL.Path)
		next(w, r)
	}
}

routes := []*webgo.Route{
	{
		Name:     "hello",
		Method:   http.MethodGet,
		Pattern:  "/",
		Handlers: []http.HandlerFunc{loggingMiddleware, hello},
	},
}

4. 静态文件服务

routes := []*webgo.Route{
	{
		Name:    "static",
		Method:  http.MethodGet,
		Pattern: "/static/:filename",
		Handlers: []http.HandlerFunc{
			func(w http.ResponseWriter, r *http.Request) {
				params := webgo.Context(r).Params()
				http.ServeFile(w, r, "static/"+params["filename"])
			},
		},
	},
}

5. JSON响应

func getUsers(w http.ResponseWriter, r *http.Request) {
	users := []struct {
		ID   int    `json:"id"`
		Name string `json:"name"`
	}{
		{1, "Alice"},
		{2, "Bob"},
	}
	
	webgo.R200(w, users)
}

高级功能

1. 自定义错误处理

func customErrorHandler(w http.ResponseWriter, r *http.Request, err error) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusInternalServerError)
	json.NewEncoder(w).Encode(map[string]string{
		"error": err.Error(),
	})
}

cfg := &webgo.Config{
	Host:         "localhost",
	Port:         "8080",
	ErrorHandler: customErrorHandler,
}

2. 优雅关闭

func main() {
	// ... 路由和配置初始化
	
	// 设置优雅关闭
	webgo.GracefulShutdown(router, &webgo.GracefulConfig{
		Timeout: 10 * time.Second,
		PreHook: func() {
			fmt.Println("Shutting down server...")
		},
		PostHook: func() {
			fmt.Println("Server shutdown complete")
		},
	})
}

3. CORS支持

func enableCORS(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
		
		if r.Method == http.MethodOptions {
			w.WriteHeader(http.StatusOK)
			return
		}
		
		next(w, r)
	}
}

完整示例

下面是一个完整的REST API示例:

package main

import (
	"encoding/json"
	"net/http"
	"strconv"
	
	"github.com/bnkamalesh/webgo/v6"
)

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

var users = []User{
	{1, "Alice"},
	{2, "Bob"},
}

func getUsers(w http.ResponseWriter, r *http.Request) {
	webgo.R200(w, users)
}

func getUser(w http.ResponseWriter, r *http.Request) {
	params := webgo.Context(r).Params()
	id, err := strconv.Atoi(params["id"])
	if err != nil {
		webgo.R400(w, "Invalid user ID")
		return
	}
	
	for _, user := range users {
		if user.ID == id {
			webgo.R200(w, user)
			return
		}
	}
	
	webgo.R404(w, "User not found")
}

func createUser(w http.ResponseWriter, r *http.Request) {
	var newUser User
	err := json.NewDecoder(r.Body).Decode(&newUser)
	if err != nil {
		webgo.R400(w, "Invalid request body")
		return
	}
	
	users = append(users, newUser)
	webgo.R201(w, newUser)
}

func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		webgo.LOGHANDLER.Info(r.Method, r.URL.Path)
		next(w, r)
	}
}

func main() {
	routes := []*webgo.Route{
		{
			Name:     "get-users",
			Method:   http.MethodGet,
			Pattern:  "/users",
			Handlers: []http.HandlerFunc{loggingMiddleware, getUsers},
		},
		{
			Name:     "get-user",
			Method:   http.MethodGet,
			Pattern:  "/users/:id",
			Handlers: []http.HandlerFunc{loggingMiddleware, getUser},
		},
		{
			Name:     "create-user",
			Method:   http.MethodPost,
			Pattern:  "/users",
			Handlers: []http.HandlerFunc{loggingMiddleware, createUser},
		},
	}
	
	cfg := &webgo.Config{
		Host:         "localhost",
		Port:         "8080",
		ReadTimeout:  10,
		WriteTimeout: 10,
	}
	
	router := webgo.NewRouter(cfg, routes...)
	webgo.GracefulShutdown(router)
}

WebGo是一个非常适合构建小型到中型Web应用的轻量级框架,它提供了足够的功能而不引入过多的复杂性。通过上述示例,你可以快速开始使用WebGo构建自己的Golang Web应用。

回到顶部