使用 Golang 和模板引擎创建网站

科技   2024-12-17 12:57   广东  

在过去,人们通常使用 HTML、CSS 和 JavaScript 来构建网站,同时在后端使用 PHP。如今,已经有许多 JavaScript 框架可供选择,比如 React.js、Next.js、Vue.js、Nuxt、Svelte、SvelteKit、Astro 等等。

在本文中,我将尝试使用 Golang、HTML、CSS 和一些 JavaScript 来创建我的网站。前端 HTML 模板部分将使用Templ。如果你熟悉 Ruby on Rails 或 Laravel,那么你可能已经了解 HTML 模板的概念。Rails 提供 ERB,Laravel 提供 Blade,它们的目的都是将后端代码与 HTML 直接集成,同时创建模块化的 HTML 模块以便在项目中复用。


安装 Templ

首先,我们需要安装 Templ 的最新版本(本文撰写时的版本为 v0.2.778,尚未达到 v1 版本)。

go install github.com/a-h/templ/cmd/templ@latest

安装完成后,我们可以开始创建一个空的 Golang 项目。假设项目名称为personal

mkdir personal && cd personal  
touch main.go  
go mod init personal

现在,项目已经初始化完成。接下来,我们将在main.go 文件中创建一个简单的 HTTP 服务器。在本文中,我将使用Echo 框架。


创建 HTTP 服务器

以下是main.go 文件的代码:

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"
    "os/signal"
    "personal/internal/config"
    "syscall"

    "github.com/caarlos0/env/v11"
    "github.com/labstack/echo/v4"
    "golang.org/x/net/http2"
    "golang.org/x/net/http2/h2c"
)

func main() {
    cfg, err := env.ParseAs[config.Config]()
    if err != nil {
        log.Println("error loading config")
    }

    e := echo.New()

    h2s := &http2.Server{
        MaxConcurrentStreams: 250,
        MaxReadFrameSize:     1048576,
        IdleTimeout:          cfg.GracefulTimeout,
    }

    s := http.Server{
        Addr:    fmt.Sprintf(":%s", cfg.Port),
        Handler: h2c.NewHandler(e, h2s),
    }

    log.Printf("server running on port: %s", cfg.Port)

    gofunc() {
        if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Println("shutting down the server")
        }
    }()

    quit := make(chan os.Signal, 1)
    signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
    <-quit

    log.Println("shutting down server...")

    ctx, cancel := context.WithTimeout(context.Background(), cfg.GracefulTimeout)
    defer cancel()

    if err := s.Shutdown(ctx); err != nil {
        log.Println("server forced to shutdown")
    }

    log.Println("server exiting")
}

运行以下命令以安装所有依赖项:

go mod tidy

接下来,创建一个名为config.go 的文件,用于存储服务器的配置信息:

package config

import "time"

type Config struct {
    Port            string        `env:"PORT" envDefault:"8080"`
    Env             string        `env:"ENV" envDefault:"dev"`
    GracefulTimeout time.Duration `env:"GRACEFUL_TIMEOUT" envDefault:"10s"`
}

为了确保服务器正常运行,可以在终端中运行以下命令:

go run main.go

如果一切正常,终端会显示类似以下的输出:

运行结果

集成 Templ

在服务器可以正常运行后,我们开始将 Templ 集成到项目中。首先,在internal 目录下创建一个名为views 的文件夹,路径为/personal/internal/views。然后创建一个名为layout.templ 的文件,用于定义项目的基础布局。

以下是layout.templ 的代码:

package views

templ head(title string, description string) {
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>{title}</title>
        <meta name="description" content={description} />
        <style>
            html {
                --font-sans: 'Manrope', sans-serif;
                --font-mono: 'JetBrains Mono', monospace;
                scroll-behavior: smooth;
            }

            .app {
                display: flex;
                flex-direction: column;
                min-height: 100vh;
            }

            main {
                flex: 1;
                display: flex;
                flex-direction: column;
                padding: 1rem;
                width: 100%;
                max-width: 64rem;
                margin: 0 auto;
                box-sizing: border-box;
            }
        </style>
    </head>
}

templ Layout(title string, description string, content templ.Component) {
    <!DOCTYPE html>
    <html>
        @head(title, description)
        <body>
            <div class="app">
                <main>
                    @content
                </main>
            </div>
        </body>
    </html>
}

上述代码中,我们定义了一个名为Layout 的 HTML 布局函数,它包含三个参数:titledescription 和content。同时,我们还定义了一个head 函数,用于存储网站的元信息。

注意:可以使用 VSCode 的 Templ 插件 来更方便地导航和编辑 Templ 函数。

接下来,运行以下命令生成 Golang 文件,以便在代码中调用 Templ 函数:

templ generate

如果终端提示templ version check: templ not found in go.mod file,不要担心。运行以下命令将 Templ 添加到go.mod 文件中:

go get github.com/a-h/templ

再次运行templ generate,你会在/personal/internal/views 目录下看到一个名为layout_templ.go 的文件,这是 Templ 自动生成的代码文件。


创建主页

接下来,我们为项目创建一个简单的主页。在/personal/internal/views 目录下创建一个名为home.templ 的文件,内容如下:

package views

templ Home() {
    <section>
        <p>Hello World.</p>
    </section>
}

然后运行以下命令生成对应的 Golang 文件:

templ generate

渲染模板

为了在 Echo 的路由中渲染模板,我们需要创建一个渲染函数。在personal/pkg/renderer 目录下创建一个文件,并添加以下代码:

package renderer

import (
    "github.com/a-h/templ"
    "github.com/labstack/echo/v4"
)

func Render(c echo.Context, statusCode int, t templ.Component) error {
    buf := templ.GetBuffer()
    defer templ.ReleaseBuffer(buf)

    if err := t.Render(c.Request().Context(), buf); err != nil {
        return err
    }

    return c.HTML(statusCode, buf.String())
}

这个函数会将模板渲染为字节缓冲区,然后通过c.HTML 方法将其转换为 HTML 响应。


修改主程序

最后,修改main.go 文件,添加路由并渲染模板:

package main

import (
    ...
    "personal/pkg/renderer"
)

func main() {
    ...
    e.GET("/"func(c echo.Context) error {
        return renderer.Render(c, http.StatusOK,
            views.Layout("Home",
                "Zainokta's home page, feels like home",
                views.Home()))
    })
    ...
}

运行以下命令启动服务器:

go run main.go

访问http://localhost:8080/,你将看到以下页面内容:

Hello World 页面

总结

通过本文的步骤,我们成功使用 Golang 和 Templ 创建了一个简单的网站。Templ 提供了强大的 HTML 模板功能,使得前后端的集成更加便捷。你可以基于本文的示例代码进一步扩展和自定义你的项目。

点击关注并扫码添加进交流群
免费领取「Go 语言」学习资料

源自开发者
专注于提供关于Go语言的实用教程、案例分析、最新趋势,以及云原生技术的深度解析和实践经验分享。
 最新文章