实践Golang语言N层应用架构

本文涉及的产品
可观测可视化 Grafana 版,10个用户账号 1个月
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。

1 简介:

本文首先概述了N层体系结构的基本概念,说明了不同逻辑功能的应用程序如何被封装到不同的构件中。

接着,详细列出了在Go语言中对应的构件名称,包括前端框架(如Vue.js、React)替代Applet,Gin的处理函数和中间件对应Servlet,依赖注入和配置管理替代EJB容器,使用中间件管理会话对应SessionBean,以及使用ORM库(如gorm或ent)进行数据库交互对应EntityBean。

最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。

  • 回望N层体系结构

很多平台采用了多层分布式作为应用程序模型,比如J2EE平台实现不同逻辑功能的应用程序被封装到不同的构件中,处于不同层次的构件可被分别部署到不同的机器中。

question_ans.png

如下图是已完成N层体系结构,

客户端         Web               (EJB容器)       DB

浏览器      Web服务器         Simple 
                               Bean   -->      (EntityBean)  -->  ----
HTML        <--  JSP              --->              <---   |  |
(Applet)  -->   (Servlet) <---    (SessionBean)   <--          ----

    J2EE 的N层体系结构示意图。

在该平台的N层体系结构应用程序模型中,实现不同逻辑功能的应用程序被封装到不同的构件中,
比如浏览器 HTML对应构件Applet,JSP对应构件Servlet,EJB容器对应 Bean(包括Simple Bean,SessionBean),与数据库交互有EntityBean,这样对应用程序就有较好的整体一致性的开发体验,

2 实现N层体系结构

假如我们要在golang语言中利用Gin框架的构件实现N层结构,或者借助其他web开发框架对应构件,以下为go语言中对应的构件名称

  • Applet

在现代 web 开发中,Applet 已不再常用。
一般使用前端框架如 Vue.js、React 或 Angular 来实现类似的功能。
它们与服务器通过 RESTful API 进行交互。

  • Servlet

在go语言框架中,比如Gin 的处理函数(Handler)和中间件(Middleware)可以看作是 Servlet 的对应物。它们负责处理 HTTP 请求和生成响应。

  • EJB 容器。

Go 语言中没有直接对应的 EJB 容器,但 Gin 框架及其生态系统中有很多库和工具可以实现类似的功能。
例如:

Dependency Injection (DI):可以使用依赖注入库如 google/wire 或 uber/dig。
Configuration Management:可以使用 viper 来管理配置。
  • SessionBean

在 Gin 框架中,可以使用中间件来管理会话。
常用的会话中间件包括 gin-contrib/sessions,它可以处理会话数据的存储和管理。

  • EntityBean

对应于与数据库交互的 EntityBean,在 Go 语言中,常用 ORM 库如 gorm 或 ent 可以实现类似的功能。
它们提供了与数据库进行 CRUD 操作的方便方法。

3 go 语言N层体系实例:

实现 Handler(Servlet)

package main

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

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080
}

实现 Session Management(SessionBean)

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
)

func main() {
    r := gin.Default()
    store := cookie.NewStore([]byte("secret"))
    r.Use(sessions.Sessions("mysession", store))

    r.GET("/session", func(c *gin.Context) {
        session := sessions.Default(c)
        var count int
        v := session.Get("count")
        if v == nil {
            count = 0
        } else {
            count = v.(int)
            count++
        }
        session.Set("count", count)
        session.Save()
        c.JSON(200, gin.H{"count": count})
    })

    r.Run(":8080")
}

4 实现数据库ORM操作实例 Database Interaction(EntityBean)

  • 使用gorm

          package main
    
          import (
              "github.com/gin-gonic/gin"
              "gorm.io/driver/sqlite"
              "gorm.io/gorm"
          )
    
          type User struct {
              ID   uint   `json:"id" gorm:"primaryKey"`
              Name string `json:"name"`
          }
    

创建ORM对象映射并操作数据

        func main() {
            db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
            if err != nil {
                panic("failed to connect database")
            }

    db.AutoMigrate(&User{})

    r := gin.Default()

    r.POST("/users", func(c *gin.Context) {
        var user User
        if err := c.ShouldBindJSON(&user); err == nil {
            db.Create(&user)
            c.JSON(200, user)
        } else {
            c.JSON(400, gin.H{"error": err.Error()})
        }
    })

    r.GET("/users/:id", func(c *gin.Context) {
        var user User
        if err := db.First(&user, c.Param("id")).Error; err != nil {
            c.JSON(404, gin.H{"error": "User not found"})
        } else {
            c.JSON(200, user)
        }
    })

    r.Run(":8080")
}

5 使用ent的ORM数据操作

  • 使用 ent

结合 ent 作为 ORM 的完整示例,包括处理 HTTP 请求(Servlet)、会话管理(SessionBean)和数据库交互(EntityBean)。

项目结构

myapp/
├── main.go
├── ent/
│   ├── generate.go
│   ├── schema/
│   │   └── user.go
go.mod

首先,初始化一个新的 Go 模块并添加所需的依赖:

go mod init myapp
go get github.com/gin-gonic/gin
go get github.com/gin-contrib/sessions
go get github.com/gin-contrib/sessions/cookie
go get entgo.io/ent
go get entgo.io/ent/entc
go get entgo.io/ent/dialect/sqlite
ent/schema/user.go

创建 User 数据模型:

package schema

import (
    "entgo.io/ent"
    "entgo.io/ent/schema/field"
)

type User struct {
    ent.Schema
}

func (User) Fields() []ent.Field {
    return []ent.Field{
        field.String("name").NotEmpty(),
    }
}

func (User) Edges() []ent.Edge {
    return nil
}
ent/generate.go

生成 ent 代码:

package ent

//go:generate go run entgo.io/ent/cmd/ent generate ./schema

然后运行 go generate ./ent 生成代码。

main.go

在 main.go 中,设置 Gin 框架,配置会话管理,并实现 CRUD 操作:

package main

import (
    "context"
    "log"
    "net/http"

    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/gin"
    "entgo.io/ent/dialect/sqlite"
    "entgo.io/ent/dialect"
    "myapp/ent"
    _ "github.com/mattn/go-sqlite3"
)

func main() {

使用ent实例化数据库操作

    // Initialize ent client
    client, err := ent.Open(dialect.SQLite, "file:ent?mode=memory&cache=shared&_fk=1")
    if err != nil {
        log.Fatalf("failed opening connection to sqlite: %v", err)
    }
    defer client.Close()
    // Run the auto migration tool.
    if err := client.Schema.Create(context.Background()); err != nil {
        log.Fatalf("failed creating schema resources: %v", err)
    }

    r := gin.Default()

设置会话存储和数据库操作

    // Set up session store
    store := cookie.NewStore([]byte("secret"))
    r.Use(sessions.Sessions("mysession", store))

    // Routes
    r.POST("/users", func(c *gin.Context) {
        var user struct {
            Name string `json:"name"`
        }
        if err := c.ShouldBindJSON(&user); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }

        u, err := client.User.Create().SetName(user.Name).Save(context.Background())
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
        c.JSON(http.StatusOK, u)
    })

    r.GET("/users/:id", func(c *gin.Context) {
        id := c.Param("id")
        u, err := client.User.Get(context.Background(), id)
        if err != nil {
            c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
            return
        }
        c.JSON(http.StatusOK, u)
    })

会话接口中实现了一个访问计数器,每次GET调用该接口将增加计数并保存到会话数据中。

    r.GET("/session", func(c *gin.Context) {
        session := sessions.Default(c)
        var count int
        v := session.Get("count")
        if v == nil {
            count = 0
        } else {
            count = v.(int)
            count++
        }
        session.Set("count", count)
        session.Save()
        c.JSON(http.StatusOK, gin.H{"count": count})
    })

    r.Run(":8080")
}

6 运行项目

确保所有依赖和生成的代码都已经准备好,然后运行应用:

go run main.go

现在,应用将在 http://localhost:8080 运行,可以使用 curl 或 Postman 等工具测试以下接口:

创建用户:POST /users
获取用户:GET /users/:id
会话管理:GET /session

7 小结

本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。

示例中使用了gorm和ent作为ORM工具,展示了如何创建用户、获取用户信息以及管理会话数据。最后,强调了运行项目的步骤,并总结了如何在Gin框架中结合ent实现N层体系结构的基本功能。

这两个示例展示了如何在 Gin 框架中使用ORM来处理数据库交互,同时实现会话管理和基本的 HTTP 请求处理,实际的项目开发中可能需要更深入更自由地使用SQL编写复杂的查询,相比ORM工具此时使用查询生成器更具有优势。

目录
相关文章
|
9天前
|
监控 Java 持续交付
后端开发中的微服务架构实践与挑战####
在当今快速迭代的软件开发领域,微服务架构以其灵活性和可扩展性成为众多企业的首选。本文探讨了微服务架构的核心概念、实施策略及面临的主要挑战,旨在为后端开发者提供一个全面的指南。通过分析真实案例,揭示微服务在提升系统敏捷性的同时,如何有效应对分布式系统的复杂性问题。 ####
|
2天前
|
缓存 负载均衡 API
后端开发中的微服务架构实践与挑战####
在数字化转型的浪潮中,微服务架构凭借其高度的可扩展性、灵活性及易于维护的特点,成为众多企业后端开发的首选架构模式。本文将深入探讨微服务架构的核心理念,通过具体案例分析其在实际应用中的实践策略与面临的挑战,为读者提供一份详尽的微服务架构实施指南。 ####
|
4天前
|
消息中间件 负载均衡 测试技术
后端开发中的微服务架构实践与挑战####
本文旨在探讨微服务架构在后端开发中的应用实践,深入分析其带来的优势与面临的挑战。通过剖析真实案例,揭示微服务转型过程中的关键技术决策、服务拆分策略、以及如何有效应对分布式系统的复杂性问题。文章还将提供一套评估企业是否适合采用微服务架构的框架,帮助读者更好地理解这一架构模式,并为企业的技术选型提供参考。 ####
|
3天前
|
运维 监控 安全
深入理解微服务架构:设计原则、挑战与实践
深入理解微服务架构:设计原则、挑战与实践
|
8天前
|
Cloud Native Devops 持续交付
云原生架构的演进与实践
本文深入探讨了云原生架构的核心概念、技术组件及其在现代软件开发中的应用。通过分析容器化、微服务、持续集成/持续部署(CI/CD)等关键技术,揭示了这些技术如何共同促进应用程序的灵活性、可扩展性和高可用性。文章还讨论了云原生架构实施过程中面临的挑战和最佳实践,旨在为开发者和企业提供一套实用的指导方针,以便更有效地利用云计算资源,加速数字化转型的步伐。
23 5
|
10天前
|
Cloud Native 安全 API
云原生架构下的微服务治理策略与实践####
—透过云原生的棱镜,探索微服务架构下的挑战与应对之道 本文旨在探讨云原生环境下,微服务架构所面临的关键挑战及有效的治理策略。随着云计算技术的深入发展,越来越多的企业选择采用云原生架构来构建和部署其应用程序,以期获得更高的灵活性、可扩展性和效率。然而,微服务架构的复杂性也带来了服务发现、负载均衡、故障恢复等一系列治理难题。本文将深入分析这些问题,并提出一套基于云原生技术栈的微服务治理框架,包括服务网格的应用、API网关的集成、以及动态配置管理等关键方面,旨在为企业实现高效、稳定的微服务架构提供参考路径。 ####
34 5
|
13天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
11天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型浪潮中,企业纷纷拥抱云计算,而云原生架构作为其核心技术支撑,正引领着一场深刻的技术变革。本文聚焦于云原生环境下微服务架构的治理策略与实践,探讨如何通过精细化的服务管理、动态的流量调度、高效的故障恢复机制以及持续的监控优化,构建弹性、可靠且易于维护的分布式系统。我们将深入剖析微服务治理的核心要素,结合具体案例,揭示其在提升系统稳定性、扩展性和敏捷性方面的关键作用,为读者提供一套切实可行的云原生微服务治理指南。 ####
|
11天前
|
消息中间件 缓存 Cloud Native
云原生架构下的性能优化实践与挑战####
随着企业数字化转型的加速,云原生架构以其高度解耦、弹性伸缩和快速迭代的特性,成为现代软件开发的首选模式。本文深入探讨了云原生环境下性能优化的关键策略与面临的主要挑战,通过案例分析,揭示了如何有效利用容器化、微服务、动态调度等技术手段提升应用性能,同时指出了在复杂云环境中确保系统稳定性和高效性的难题,为开发者和架构师提供了实战指南。 ####
25 3
|
11天前
|
运维 Kubernetes Cloud Native
深入理解云原生架构:从理论到实践
【10月更文挑战第38天】本文将引导读者深入探索云原生技术的核心概念,以及如何将这些概念应用于实际的软件开发和运维中。我们将从云原生的基本定义出发,逐步展开其背后的设计哲学、关键技术组件,并以一个具体的代码示例来演示云原生应用的构建过程。无论你是云原生技术的初学者,还是希望深化理解的开发者,这篇文章都将为你提供有价值的见解和实操指南。
下一篇
无影云桌面