Golang Web应用架构设计与实践

Golang Web应用架构设计与实践 我刚开始使用Go语言。我想用标准库编写一个Web应用程序。请问推荐的Web应用程序文件结构是什么样的?

14 回复

感谢。我几天没来这里了,刚刚看到这个。正准备阅读这篇文章。

更多关于Golang Web应用架构设计与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你们认为标准库适合用来开发Web应用程序吗?还是我应该使用其他工具?

请查看这篇文章:《编写Web应用程序》

CryptoBaymax:

你们认为标准库适合用来开发Web应用程序吗?

是的。

你的cmd目录是什么?这将是我用Go编写的第一个Web应用程序。我一直都是用PHP来编写这类应用的。

我发现这篇Medium文章中的建议非常实用且直观。

使用标准库入门相当容易,但我确实发现使用第三方库能为应用程序代码提供某种结构。

就个人而言,我使用Mux并发现自己能够更快地启动项目。

那么我不需要使用像mux这样的库,只用标准库就可以了吗?标准库应该足以支持博客、搜索、用户认证、数据库等功能。我是新手,之前有PHP背景。

这对我来说很有道理,看起来是个不错的结构。不过有几点我不太确定。handler目录是做什么用的?模板和CSS文件应该放在哪里?main.go文件里应该包含哪些内容?是只包含主要的逻辑和路由,还是也应该包含服务器配置信息?

Go语言通常避免在常规应用中使用多个包/文件夹。 一个不错的入门示例:

/cmd
.. main.go
/myapp
.. model.go
.. server.go <-- 你的http处理程序放在这里
.. service.go
/internals
.. someobscurestuff.go

这对我来说有点新鲜。我一直都是用PHP从零开始写项目。不喜欢用框架,所以总是自己从头开始写。但后来发现有些事情本可以做得更好,比如使用模板之类的东西,而不是写那么多不必要的代码。还有模型,我从未使用过。在阅读相关资料后,我发现它们非常有用。所以我打算在下一个项目中使用这些东西。

可能是最简洁的架构

├── driver // 所有数据库连接(mysql、psql、mongo)
├── handler // 所有处理器
│   └── http
│   └── websocket
 |── models // 所有全局数据模型(请求json模型、响应模型等)
└── repository // 数据库查询接口
    └── user // 查询用户的数据库函数
    └── posts // 查询帖子...

看看这个,

在 Go 中构建应用程序

我曾经将我的 main.go 文件放在项目的根目录中,这样当有人运行 “go get” 时,我的应用程序就会自动安装。然而,将 main.go 文件和我的应用程序逻辑放在同一个包中有两个后果:

  1. 这使得我的应用程序无法作为库使用。
  1. 我只能有一个应用程序二进制文件。

我找到的解决这个问题的最佳方法是简单地在我的项目中使用一个 “cmd” 目录,其中的每个子目录都是一个应用程序二进制文件。我最初在 Brad Fitzpatrick 的 Camlistore 项目中发现了这种方法,他使用了多个应用程序二进制文件:

对于使用Go标准库构建Web应用,推荐采用以下文件结构,这种结构清晰且易于维护:

myapp/
├── cmd/
│   └── web/
│       └── main.go          # 应用入口点
├── internal/
│   ├── handlers/           # HTTP处理器
│   │   ├── user.go
│   │   └── home.go
│   ├── models/             # 数据模型
│   │   └── user.go
│   ├── middleware/         # 中间件
│   │   └── auth.go
│   └── config/             # 配置
│       └── config.go
├── pkg/
│   └── utils/              # 可复用工具
│       └── validation.go
├── static/                 # 静态文件
│   ├── css/
│   ├── js/
│   └── images/
├── templates/              # HTML模板
│   ├── base.html
│   ├── home.html
│   └── user.html
├── go.mod
└── go.sum

具体实现示例:

cmd/web/main.go - 应用入口:

package main

import (
    "log"
    "net/http"
    "myapp/internal/handlers"
    "myapp/internal/middleware"
)

func main() {
    mux := http.NewServeMux()
    
    // 静态文件服务
    fs := http.FileServer(http.Dir("./static"))
    mux.Handle("/static/", http.StripPrefix("/static/", fs))
    
    // 路由设置
    mux.HandleFunc("/", handlers.HomeHandler)
    mux.HandleFunc("/users", handlers.UserHandler)
    
    // 应用中间件
    handler := middleware.Logging(mux)
    handler = middleware.Auth(handler)
    
    log.Println("服务器启动在 :8080")
    log.Fatal(http.ListenAndServe(":8080", handler))
}

internal/handlers/home.go - 处理器示例:

package handlers

import (
    "html/template"
    "net/http"
)

func HomeHandler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        http.NotFound(w, r)
        return
    }
    
    tmpl := template.Must(template.ParseFiles(
        "templates/base.html",
        "templates/home.html",
    ))
    
    data := struct {
        Title string
    }{
        Title: "首页",
    }
    
    tmpl.ExecuteTemplate(w, "base", data)
}

internal/middleware/auth.go - 中间件示例:

package middleware

import (
    "net/http"
)

func Auth(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 简单的认证逻辑
        token := r.Header.Get("Authorization")
        if token == "" {
            http.Error(w, "未授权", http.StatusUnauthorized)
            return
        }
        
        next.ServeHTTP(w, r)
    })
}

internal/middleware/logging.go - 日志中间件:

package middleware

import (
    "log"
    "net/http"
    "time"
)

func Logging(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        log.Printf("%s %s %v", r.Method, r.URL.Path, time.Since(start))
    })
}

这种结构遵循Go项目的标准布局,将不同职责的代码分离到相应目录中,便于团队协作和代码维护。

回到顶部