代码优化-如何减少if-else以提升代码质量(使用表驱动)

0x00 前言

  在日常编写代码时常会遇到多条件判断情况,在我们的编写过程中常会使用if-else或switch来进行校验,但这种情况会导致代码可读性降低,本文将使用表驱动的方式进行if-else的代码块重写

0x01 原理

  将所需要的判断调节通过一张hash表进行注册,使用时只需要对hash表进行查询即可,降低了代码量的同时增加可读性。

0x02 代码

需求:针对一条URL,对不同的请求进行不同的响应。

历史代码:

代码结构为

D:.
│  go.mod
│  go.sum
│  main.go
│
├─handler
│      main_handler.go
│      table_driver_handler.go
│
└─register
        register.go

常规写法 main_handler.go

func MainHandler(c *gin.Context) {
	method := c.Request.Method
	if method == "GET" {
		c.JSON(http.StatusOK, gin.H{
			"message": "GET Request",
		})
	} else if method == "POST" {
		c.JSON(http.StatusOK, gin.H{
			"message": "POST Request",
		})
	} else if method == "DELETE" {
		c.JSON(http.StatusOK, gin.H{
			"message": "DELETE Request",
		})
	} else {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": "No Such Function",
		})
	}
	return
}

使用表驱动时

注册代码 register.go

package register

// 注册表
var (
	Res = make(map[string]string)
)

// 添加内容
func putMap(method, res string) {
	Res[method] = res
}

// 注册内容
func registerRequest(res map[string]string) {
	putMap("GET", "GET Request")
	putMap("POST", "POST Request")
	putMap("DELETE", "DELETE Request")
}

// Go在初始化项目时会读取项目中所有init提前编译
func init() {
	registerRequest(Res)
}

运行时的注册效果

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

register.Res: map[DELETE:DELETE Request GET:GET Request POST:POST Request]

处理代码 table_driver_handler.go

package handler

import (
	"net/http"
	"tableDriver/register"

	"github.com/gin-gonic/gin"
)

func TableHandler(c *gin.Context) {
	method := c.Request.Method
	if register.Res[method] != "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": "No Such Function",
		})
	} else {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": register.Res[method],
		})
	}
	return
}

主函数

package main

import (
	"fmt"
	"tableDriver/handler"
	"tableDriver/register"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.New()
	r.Use(gin.Logger(), gin.Recovery())
	gin.SetMode(gin.DebugMode)
	fmt.Printf("register.Res: %v\n", register.Res)
	r.Any("/api/common/v1", handler.MainHandler)
	r.Any("/api/table-driver/v1", handler.MainHandler)
	r.Run("0.0.0.0:30999")
}

0x03 分析

  可以发现,常规写法代码由四个判断条件组成,可读性较差且拓展时需要在后续添加if判断语句,拓展性差。

  而使用表驱动写法代码可读性提升,并且易于扩展。

0x04 总结

  综上所述,使用表驱动可以有效的提升代码的可读性与扩展性,在遇到多条件判断的情况时可以采用该方法,但要注意返回结果需要通用,否则不宜采用。

0x05 附录

  上文所述是只定义了返回数据的表驱动,同样我们可以定义函数来作为表的value值,示例如下。
register/register.go

package register

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

// 设置 funHandler 为带参数 gin.Context 的函数类
type funHandler func(*gin.Context)

// FunMap 注册表
var FunMap = make(map[string]funHandler)

// Go在初始化项目时会读取项目中所有init提前编译,即初始化注册表
func init() {
	FunMap["GET"] = func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "GET Request",
		})
	}
	FunMap["POST"] = func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "POST Request",
		})
	}
	FunMap["DELETE"] = func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "DELETE Request",
		})
	}
}

TableHandler如下所示

package handler

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"tableDriver/register"
)

// TableHandler 表驱动handler
func TableHandler(c *gin.Context) {
	method := c.Request.Method
	funHandler, ok := register.FunMap[method]
	if !ok {
		c.JSON(http.StatusOK, gin.H{
			"message": "No Such Function",
		})
		return
	}
	funHandler(c)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值