Golang中的GTML工具 - 让HTML编写变得轻松自如 🍃

Golang中的GTML工具 - 让HTML编写变得轻松自如 🍃 https://github.com/phillip-england/gtml

什么是 GTML?

GTML 是一个编译器,它将 .html 文件转换为可组合的 .go 函数。可以把它看作是 Go 语言中的 JSX

Hello, World

将以下内容:

<div _component="Greeting">
    <h1>Hello, $prop("name")</h1>
</div>

转换为:

func Greeting(name string) string {
    var builder strings.Builder
    builder.WriteString(`<div _component="Greeting" _id="0"><h1>Hello, `)
    builder.WriteString(name)
    builder.WriteString(`!</h1>`)
    return builder.String()
}

安装

确保使用 go 1.22.3 或更高版本,克隆仓库并在您的系统上构建二进制文件。

git clone https://github.com/phillip-england/gtml;
cd gtml;
go build -o gtml main.go;

之后您将得到一个可以移动到 PATH 路径下的二进制文件。

mv gtml ./some/dir/on/your/path

更多关于Golang中的GTML工具 - 让HTML编写变得轻松自如 🍃的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中的GTML工具 - 让HTML编写变得轻松自如 🍃的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


GTML确实是一个很有意思的工具,它通过编译时转换的方式,在Go中实现了类似JSX的声明式HTML编写体验。从技术实现来看,它主要解决了两个痛点:类型安全的HTML生成和组件化开发。

让我通过几个示例来展示GTML的实际应用:

基础组件示例

<!-- button.html -->
<button _component="PrimaryButton" class="btn btn-primary">
    $prop("text")
</button>

编译后生成:

func PrimaryButton(text string) string {
    var builder strings.Builder
    builder.WriteString(`<button _component="PrimaryButton" _id="0" class="btn btn-primary">`)
    builder.WriteString(text)
    builder.WriteString(`</button>`)
    return builder.String()
}

带条件渲染的组件

<!-- user-card.html -->
<div _component="UserCard">
    <div class="user-avatar">
        $if(prop("avatar")) {
            <img src="$prop("avatar")" alt="$prop("name")">
        } $else {
            <div class="default-avatar">
                ${strings.ToUpper(prop("name")[0:1])}
            </div>
        }
    </div>
    <h3>$prop("name")</h3>
    $if(prop("isAdmin")) {
        <span class="badge">Admin</span>
    }
</div>

循环渲染示例

<!-- todo-list.html -->
<ul _component="TodoList">
    $for(_, item := range prop("items")) {
        <li class="todo-item $if(item.Completed){completed}">
            <input type="checkbox" $if(item.Completed){checked}>
            <span>$item.Title</span>
        </li>
    }
</ul>

嵌套组件使用

// 生成的Go代码可以直接嵌套调用
func UserProfile(user User) string {
    var builder strings.Builder
    builder.WriteString(`<div class="profile">`)
    builder.WriteString(UserCard(user.Name, user.Avatar, user.IsAdmin))
    builder.WriteString(TodoList(user.Todos))
    builder.WriteString(`</div>`)
    return builder.String()
}

类型安全的数据绑定

GTML在编译时会进行类型检查,确保属性传递的正确性:

<!-- product-card.html -->
<div _component="ProductCard">
    <h4>$prop("product").Name</h4>
    <p>Price: $fmt.Sprintf("$%.2f", prop("product").Price)</p>
    <button onclick="addToCart($prop("product").ID)">
        Add to Cart
    </button>
</div>

性能考虑

GTML生成的代码使用strings.Builder进行高效的字符串拼接,避免了频繁的内存分配:

// 编译后的优化代码示例
func LargeList(items []Item) string {
    var builder strings.Builder
    // 预分配内存,提高性能
    builder.Grow(len(items) * 100)
    
    builder.WriteString(`<ul class="item-list">`)
    for _, item := range items {
        builder.WriteString(`<li>`)
        builder.WriteString(item.Name)
        builder.WriteString(`</li>`)
    }
    builder.WriteString(`</ul>`)
    return builder.String()
}

实际项目集成

# 在项目中集成GTML
gtml -input=./templates -output=./generated -package=components
// main.go中使用生成的组件
package main

import (
    "fmt"
    "net/http"
    "./generated/components"
)

func handler(w http.ResponseWriter, r *http.Request) {
    user := User{Name: "John", Avatar: "avatar.jpg", IsAdmin: true}
    html := components.UserProfile(user)
    w.Header().Set("Content-Type", "text/html")
    fmt.Fprint(w, html)
}

GTML的这种设计模式特别适合需要服务端渲染的Web应用,它在保持Go性能优势的同时,提供了更友好的HTML开发体验。编译时转换确保了运行时的性能,而组件化的设计提高了代码的可维护性。

回到顶部