golang常见框架

gin

简介

Gin 是一个用 Go (Golang) 编写的 Web 框架

特性

快速

基于 Radix 树的路由,小内存占用。没有反射。可预测的 API 性能。

支持中间件

传入的 HTTP 请求可以由一系列中间件和最终操作来处理。 例如:Logger,Authorization,GZIP,最终操作 DB。

Crash 处理

Gin 可以 catch 一个发生在 HTTP 请求中的 panic 并 recover 它。这样,你的服务器将始终可用。例如,你可以向 Sentry 报告这个 panic!

JSON 验证

Gin 可以解析并验证请求的 JSON,例如检查所需值的存在。

路由组

更好地组织路由。是否需要授权,不同的 API 版本…… 此外,这些组可以无限制地嵌套而不会降低性能。

错误管理

Gin 提供了一种方便的方法来收集 HTTP 请求期间发生的所有错误。最终,中间件可以将它们写入日志文件,数据库并通过网络发送。

内置渲染

Gin 为 JSON,XML 和 HTML 渲染提供了易于使用的 API。

可扩展性

新建一个中间件非常简单

安装

要安装 Gin 软件包,需要先安装 Go 并设置 Go 工作区。

1.下载并安装 gin:

$ go get -u github.com/gin-gonic/gin

或 install

$ go install github.com/gin-gonic/gin@latest

示例

package main

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

func main() {
	router := gin.Default()
	router.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	router.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

路由存储

在 Gin 框架里,采用前缀树(Trie 树),也就是压缩字段树来存储路由信息。前缀树是一种树形数据结构,它能高效地存储和查找字符串

原理概述

  • 节点结构:前缀树的每个节点代表一个字符,从根节点到某个节点的路径上经过的字符连接起来,就构成了一个字符串。
  • 压缩机制:为了节省空间和提高查找效率,Gin 对前缀树进行了压缩,将连续的字符压缩成一个节点,而不是每个字符一个节点。
  • 路由匹配:在进行路由匹配时,从根节点开始,根据请求的路径依次匹配节点,直到找到匹配的路由或者匹配失败。

示例

假设我们有以下几个路由

  1. /user
  2. /user/info
  3. /user/settings
  4. /article
前缀树结构

下面是对应的前缀树结构:

解释
  • 根节点:这是前缀树的起始点,不包含任何字符。
  • 第一层节点:有两个节点 user 和 article,分别对应 /user 和 /article 这两个路由。
  • 第二层节点:在 user 节点下,有 info 和 settings 两个节点,分别对应 /user/info 和 /user/settings 这两个路由。

代码示例

package main

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

func main() {
    r := gin.Default()

    // 定义 /user 路由
    r.GET("/user", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "message": "这是 /user 路由",
        })
    })

    // 定义 /user/info 路由
    r.GET("/user/info", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "message": "这是 /user/info 路由",
        })
    })

    // 定义 /user/settings 路由
    r.GET("/user/settings", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "message": "这是 /user/settings 路由",
        })
    })

    // 定义 /article 路由
    r.GET("/article", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "message": "这是 /article 路由",
        })
    })

    r.Run(":8080")
}    

文档

https://gin-gonic.com/zh-cn/docs/

协议

http1.1

package main

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

func main() {
    // 创建一个默认的 Gin 引擎
    r := gin.Default()

    // 定义一个简单的路由
    r.GET("/hello", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "Hello, HTTP 1.1!",
        })
    })

    // 启动服务器,默认使用 HTTP 1.1 协议
    r.Run(":8080")
}    

http2.0

package main

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

func main() {
    // 创建一个默认的 Gin 引擎
    r := gin.Default()

    // 定义一个简单的路由
    r.GET("/hello", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "Hello, HTTP 2.0!",
        })
    })

    // 启动使用 HTTP 2.0 协议的服务器,需要提供证书和私钥文件
    err := r.RunTLS(":8443", "cert.pem", "key.pem")
    if err != nil {
        panic(err)
    }
}    

websocket

代码解释

  • WebSocket 升级器upgrader 用于将 HTTP 连接升级为 WebSocket 连接,CheckOrigin 函数用于允许跨域请求。
  • WebSocket 处理函数wsHandler 函数将接收到的 HTTP 请求升级为 WebSocket 连接,然后在一个无限循环中读取客户端发送的消息,并发送响应消息。
  • 路由注册:在 main 函数中,使用 r.GET("/ws", wsHandler) 注册 WebSocket 路由。
  • 启动服务器:使用 r.Run(":8080") 启动一个监听在 8080 端口的 HTTP 1.1 服务器。
package main

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

// 定义一个 WebSocket 升级器
var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

// WebSocket 处理函数
func wsHandler(c *gin.Context) {
    // 将 HTTP 连接升级为 WebSocket 连接
    conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
    if err != nil {
        log.Println("WebSocket 升级失败:", err)
        return
    }
    defer conn.Close()

    for {
        // 读取消息
        messageType, message, err := conn.ReadMessage()
        if err != nil {
            log.Println("读取消息失败:", err)
            break
        }
        // 打印接收到的消息
        log.Printf("接收到消息: %s", string(message))

        // 发送响应消息
        err = conn.WriteMessage(messageType, []byte("已收到消息: "+string(message)))
        if err != nil {
            log.Println("发送消息失败:", err)
            break
        }
    }
}

func main() {
    // 创建一个默认的 Gin 引擎
    r := gin.Default()

    // 注册 WebSocket 路由
    r.GET("/ws", wsHandler)

    // 启动服务器,默认使用 HTTP 1.1 协议
    r.Run(":8080")
}    

中间件

package main

import (
    "github.com/gin-gonic/gin"
    "log"
    "time"
)

// LoggerMiddleware 是一个自定义的中间件,用于记录请求的处理时间
func LoggerMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 记录请求开始时间
        start := time.Now()

        // 打印请求的基本信息
        log.Printf("开始处理请求: %s %s", c.Request.Method, c.Request.URL.Path)

        // 调用 Next() 方法,将请求传递给后续的处理函数或中间件
        c.Next()

        // 记录请求结束时间
        end := time.Now()

        // 计算请求处理时间
        elapsed := end.Sub(start)

        // 打印请求处理结果和处理时间
        log.Printf("请求处理完成: %s %s,状态码: %d,处理时间: %v", c.Request.Method, c.Request.URL.Path, c.Writer.Status(), elapsed)
    }
}

func main() {
    // 创建一个默认的 Gin 引擎
    r := gin.Default()

    // 全局使用 LoggerMiddleware 中间件
    r.Use(LoggerMiddleware())

    // 定义一个简单的路由处理函数
    r.GET("/hello", func(c *gin.Context) {
        // 模拟一些处理操作
        time.Sleep(200 * time.Millisecond)
        c.JSON(200, gin.H{
            "message": "Hello, World!",
        })
    })

    // 启动服务器
    r.Run(":8080")
}
    

r.use()

后置拦截

在中间件函数中 next()表示
前面我们讲的都是到达我们定义的HTTP处理方法前进行拦截, 其实, 如果在中间件中调用gin.Context的Next()方法, 则可以请求到达并完成业务处理后, 再经过中间件后置拦截处理.

在中间件调用Next()方法, Next()方法之前的代码会在到达请求方法前执行, Next()方法之后的代码则在请求方法处理后执行.

grpc

简介

gRPC 是一个高性能、开源的远程过程调用(RPC)框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准 而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。它可以使不同平台和语言之间的服务相互通信。它的优点包括:高效性、跨平台、异步流处理、支持多种语言、安全、易于使用和开源。

Go 语言:gRPC 服务端默认会为每个请求创建一个新的 goroutine 来处理,利用 goroutine 的轻量级特性高效处理并发请求

// greeter.proto
syntax = "proto3";

package greeter;

// 请求消息
message HelloRequest {
  string name = 1;
}

// 响应消息
message HelloResponse {
  string message = 1;
}

// 服务定义
service Greeter {
  // 定义 SayHello 方法
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

protoc --go_out=. --go-grpc_out=. greeter.proto
package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "your_package_path" // 替换为实际生成的包路径
)

// server 实现了 greeter.Greeter 服务
type server struct {
    pb.UnimplementedGreeterServer
}

// SayHello 实现了 Greeter 服务的 SayHello 方法
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
    log.Printf("Received: %v", in.GetName())
    return &pb.HelloResponse{Message: "Hello " + in.GetName()}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    log.Printf("server listening at %v", lis.Addr())
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}    
package main

import (
    "context"
    "log"
    "os"
    "time"

    "google.golang.org/grpc"
    pb "your_package_path" // 替换为实际生成的包路径
)

func main() {
    // 连接到服务端
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithBlock())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)

    // 创建上下文
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    // 创建请求消息
    name := "World"
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    in := &pb.HelloRequest{Name: name}

    // 调用服务方法
    resp, err := c.SayHello(ctx, in)
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", resp.GetMessage())
}    

gnet

简介

gnet 是一个基于事件驱动的高性能和轻量级网络框架。它直接使用 epoll 和 kqueue 系统调用而非标准 Golang 网络包:net 来构建网络应用,它的工作原理类似两个开源的网络库:netty 和 libuv

这个项目存在的价值是提供一个在网络包处理方面能和 RedisHaproxy 这两个项目具有相近性能的 Go 语言网络服务器框架。

gnet 的亮点在于它是一个高性能、轻量级、非阻塞的纯 Go 实现的传输层(TCP/UDP/Unix-Socket)网络框架,开发者可以使用 gnet 来实现自己的应用层网络协议(HTTP、RPC、Redis、WebSocket 等等),从而构建出自己的应用层网络应用:比如在 gnet 上实现 HTTP 协议就可以创建出一个 HTTP 服务器 或者 Web 开发框架,实现 Redis 协议就可以创建出自己的 Redis 服务器等等。

多线程/Go 程网络模型

主从多 Reactors

I/O 事件

gnet 目前支持的 I/O 事件如下:

  • EventHandler.OnInitComplete 当 server 初始化完成之后调用。
  • EventHandler.OnOpened 当连接被打开的时候调用。
  • EventHandler.OnClosed 当连接被关闭的之后调用。
  • EventHandler.React 当 server 端接收到从 client 端发送来的数据的时候调用。(你的核心业务代码一般是写在这个方法里)
  • EventHandler.Tick 服务器启动的时候会调用一次,之后就以给定的时间间隔定时调用一次,是一个定时器方法。
  • EventHandler.PreWrite 预先写数据方法,在 server 端写数据回 client 端之前调用

github

https://github.com/panjf2000/gnet

引用

gnet: 一个轻量级且高性能的 Go 网络框架_golang gnet-CSDN博客

tars

简介

TARS 是 Linux 基金会的开源项目,它是基于名字服务使用 TARS 协议的高性能 RPC 开发框架,配套一体化的运营管理平台,并通过伸缩调度,实现运维半托管服务。

TARS 是腾讯从 2008 年到今天一直在使用的后台逻辑层的统一应用框架,覆盖腾讯 100 多个产品。目前支持 C++,Java,PHP,Nodejs,Go 语言。该框架为用户提供了涉及到开发、运维、以及测试的一整套解决方案,帮助一个产品或者服务快速开发、部署、测试、上线。 它集可扩展协议编解码、高性能 RPC 通信框架、名字路由与发现、发布监控、日志统计、配置管理等于一体,通过它可以快速用微服务的方式构建自己的稳定可靠的分布式应用,并实现完整有效的服务治理。

文档

TARS

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值