Golang中如何实现加载图标/GIF的显示功能

Golang中如何实现加载图标/GIF的显示功能 你好

用户填写表单后,数据会被发送到 Go API 服务器。前端也使用 Go。 现在,如果我使用 JavaScript 来验证表单,并且仅使用 JavaScript 提交表单,我就无法在 Go 中进行验证。

无论数据是什么,API 服务器都必须对其进行验证和处理。

我倾向于将表单转换为模型并在服务器端验证数据。之后再将其传递给 API 服务器。

在等待 API 响应时,我能否使用 Go 显示加载状态? 浏览器的控制权完全在 JavaScript 手中。如果我在 Go 前端服务器中进行验证,该如何处理 JavaScript 显示/隐藏加载状态的部分呢?


更多关于Golang中如何实现加载图标/GIF的显示功能的实战教程也可以访问 https://www.itying.com/category-94-b0.html

10 回复

Mahesh_Kumar1:

我该如何实现那个JavaScript的加载/隐藏部分

这里有一个使用Go创建表单的实时示例。我的API响应在零点几秒内完成,因此我没有实现“加载中…”的提示。但我可以创建一个模拟加载“错误”的错误。

更多关于Golang中如何实现加载图标/GIF的显示功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果能够避免,我不会使用Javascript进行验证。在性能最佳的地方进行验证。但我的目标始终是使用Go与API进行通信。

在这些情况下,我们不能使用上述的Javascript代码。是这样吗?

let loadingMessage = "Loading..."; // Customize the loading message here
  document.getElementById("subcnt").innerHTML = loadingMessage;

“Content-Type”: “application/json” 我们还能发送HTML吗?

这里你使用了JavaScript。 我有一个表单,用于获取用户详细信息(个人信息)。我在JavaScript中对它们进行验证。

现在我有两个选择。 我可以直接使用JavaScript将表单发送到API服务器。 或者我可以将表单发送到前端进行再次验证。

如果我选择JavaScript,我就无法用Golang进行验证。数据会被直接发送过去。但是,在从API得到结果/响应之前,我可以显示加载状态。

如果我选择用Golang验证,我就无法显示加载状态。在结果返回之前,会显示一个空白页面。有没有可能在这个空白页面上显示任何加载提示……?

在这些情况下,我们不能使用上面的 JavaScript。是这样吗?

也许你需要修改一些代码行,但原理是相同的。

主要区别在于,你调用 API 时,是直接通过 URL 访问 API,还是通过 Go 服务器中的一个端点。

另一个区别是,使用 JavaScript 时,你有时会填充一个现有的表单。而如我示例中使用 Go 时,你可以在一个步骤中获取一个完整的表单及其数据。

过程大致如下:

  1. 从某处(直接或间接)fetch()
  2. 等待响应(如果过程较慢,通知用户)
  3. 处理响应(填充 innerHTML 或表单)

关于这个问题,我还有一个疑问。

我的架构设置如下:

Go Web 服务器(处理模板) Go API 服务器(处理数据库请求)

目前,我已在 JavaScript 和 Go Web 服务器中实现了验证。 如果禁用了 JavaScript,则仅进行 Web 服务器端的验证。 如果启用了 JavaScript,则会同时进行 JavaScript 和 Web 服务器端的验证。

提交表单后,API 服务器会再次进行验证。 因此,对于相同的数据,我必须进行三次验证。

  1. 我是否可以跳过 Go Web 服务器的验证,只在 API 中进行?(我认为这不是一个好主意)
  2. 我是否应该建立一个公共的验证服务器(Web 服务器和 API 服务器都可以使用它(不包括 JavaScript))?它只返回布尔值和错误信息?

或者,这是否是浪费时间且浪费网络请求?

Mahesh_Kumar1:

在等待API响应时,我能否使用Golang显示加载状态。

如果你想显示加载图标/GIF,根据定义,你必须在客户端(使用JavaScript)实现。所以类似下面的方法可能有效,你使用js提交表单,但同时设置某种加载指示器:

function submitMyForm() {
   // 设置加载指示器
   document.getElementById('loadingIndicator').innerHTML += 'Loading...';
   // 提交表单
   document.getElementById("myForm").submit();
}

Mahesh_Kumar1:

那么,如果我使用JavaScript来验证表单,并且也只用JavaScript提交表单,我就无法在Golang中进行验证了。

我通常同时进行客户端和服务器端验证,因为当明知表单无效时还提交,仅仅为了往返服务器再显示错误信息,这不是一个好的用户体验。例如,如果是一个登录表单,邮箱和密码都为空,我甚至不需要发送到服务器就知道它是无效的。然而,你必须在服务器端进行验证,因为你不能信任客户端提交的值。

所以我必须对相同的数据进行三次验证。

  1. 我是否可以跳过Go Web服务器的验证,只在API中进行?(我认为这不是个好主意)
  2. 我应该有一个公共的验证服务器(Web服务器和API服务器都可以使用它(非JavaScript))吗?它只返回布尔值和错误信息?

或者这是否是浪费时间和网络请求?

这取决于你想要验证什么。但我的经验法则是:同一件事只验证一次。并且在有意义的地方进行验证。尽可能早地进行验证。从表单级别的HTML验证开始。

将验证信息(错误)放在错误的位置,可能会让用户感到沮丧。

  1. 使用 HTML 进行预验证。
  2. 不使用或仅使用基本的JavaScript验证。我个人倾向于避免在浏览器层面使用JavaScript进行验证。但这只是个人偏好。
  3. 大部分验证在发送到API之前,在Go服务器中进行。
  4. 在API服务器中不进行或仅进行少量验证。涉及数据库连接的重复项搜索或类似任务可能是个例外。
  5. 在数据库中进行最终的小规模验证(例如对唯一ID的内置测试等)。

Mahesh_Kumar1: 浏览器控制完全掌握在JavaScript手中。如果我在Golang前端服务器进行验证,该如何处理JavaScript的加载/隐藏部分?

我没有完全理解你的问题。但是有一种方法可以动态地隐藏或显示HTML。

  1. 获取模板(可以带数据或不带数据)
  2. 将HTML模板渲染到缓冲区并保存到HTML主体中
  3. 获取渲染后的HTML并保存到innerHTML的div中

处理步骤1和3的JavaScript部分:

// fetch data and populate a <div id="subcnt"></div>
function get_rec(id) {
  let url = "/" + module + "/view/" + id
  fetch(url, {
    headers: {
      "Content-Type": "application/json"
    },
    credentials: "same-origin"
  })
    .then((res) => res.text())
    .then((response) => {
      document.getElementById("subcnt").innerHTML = response;
    })
    .catch((error) => alert("Error get_rec:", error));
}

渲染页面并在需要时从API或类似地方获取数据的Go部分:

// write rendered html into buffer (html body)
func get_card(w http.ResponseWriter, module string, mode string, val string) {
	page := module + "_" + mode //add + .html if needed
	fmt.Println(page)
	data := json2map4id(module, val)
	var buf bytes.Buffer
	tpl.ExecuteTemplate(&buf, page, data)
	fmt.Fprint(w, buf.String())
}

“Content-Type”: “application/json” 我们还能发送HTML吗?

你希望得到JSON格式的响应。如果Go没有返回任何响应,你可以省略这个。

这里你使用了javascript。 我有一个表单,用来获取用户详细信息。个人信息。我在javascript中验证它们。

现在我有两个选择。 我可以直接用javascript将表单发送到API服务器。 或者我可以将表单发送到前端再次验证。

验证可以在三个地方进行:浏览器、Go服务器或数据库中。

如果我选择javascript,我就无法用Golang验证。数据会直接发送过去。

如果你使用Go进行验证,你还可以选择通过HTML和Javascript对输入进行预验证。

在Go中进行API调用的主要优势是,相比于使用Javascript发送表单,API调用更加“隐蔽”(即更安全)。

但是我可以显示加载状态,直到我从API得到结果/响应。

如果你使用自己的Go API,传输到数据库应该只需要不到一两秒。如果时间更长,请找到瓶颈并修复它们。

如果你使用外部慢速API,你可以通过某种方式通知用户。

如果我选择用Golang验证,我就无法显示加载状态。在结果返回之前,会显示一个空白页面。是否有可能在那个空白页面上显示任何加载提示…?

如果你使用Go进行验证,你可以使用 fetch() 向一个Go端点发送一个URL + JSON。然后Go可以将API的响应发送回浏览器。在等待这个响应时,你可以在 fetch 函数内做任何你想做的事情来通知用户。

我的方法是将验证分散在HTML、Go和数据库之间。如果可以避免,我不会使用Javascript进行验证。在性能最好的地方进行验证。但我的目标是始终使用Go来与API通信。

我不是Javascript的朋友,也不太熟悉它。所以我问了chatGPT如何在等待响应时向innerHTML发送消息。这意味着当你点击发送按钮时,表单会立即被替换为所需的内容。我无法确认它是否有效,但可以试试看…

function get_rec(id) {
  let loadingMessage = "Loading..."; // 在此处自定义加载消息
  document.getElementById("subcnt").innerHTML = loadingMessage;

  let url = "/" + module + "/view/" + id;
  fetch(url, {
    headers: {
      "Content-Type": "application/json"
    },
    credentials: "same-origin"
  })
    .then((res) => res.text())
    .then((response) => {
      document.getElementById("subcnt").innerHTML = response;
    })
    .catch((error) => {
      document.getElementById("subcnt").innerHTML = "An error occurred.";
      console.error("Error get_rec:", error);
    });
}

在Go中实现加载图标/GIF显示功能,通常需要结合前端技术。以下是几种实现方式:

1. 模板渲染时嵌入加载状态

// server.go
package main

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

func main() {
    tmpl := template.Must(template.ParseFiles("form.html"))
    
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        tmpl.Execute(w, nil)
    })
    
    http.HandleFunc("/submit", func(w http.ResponseWriter, r *http.Request) {
        // 验证逻辑
        if err := validateForm(r); err != nil {
            // 返回错误
            w.WriteHeader(http.StatusBadRequest)
            w.Write([]byte(err.Error()))
            return
        }
        
        // 处理数据
        time.Sleep(2 * time.Second) // 模拟处理延迟
        
        w.Write([]byte("提交成功"))
    })
    
    http.ListenAndServe(":8080", nil)
}

2. 使用HTML模板包含加载动画

<!-- form.html -->
<!DOCTYPE html>
<html>
<head>
    <style>
        .loading {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
        .spinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3498db;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
    <form id="myForm" onsubmit="submitForm(event)">
        <input type="text" name="username" required>
        <input type="email" name="email" required>
        <button type="submit">提交</button>
    </form>
    
    <div id="loading" class="loading">
        <div class="spinner"></div>
    </div>
    
    <script>
        function submitForm(e) {
            e.preventDefault();
            
            // 显示加载动画
            document.getElementById('loading').style.display = 'block';
            
            const formData = new FormData(e.target);
            
            fetch('/submit', {
                method: 'POST',
                body: formData
            })
            .then(response => {
                document.getElementById('loading').style.display = 'none';
                if (!response.ok) {
                    throw new Error('提交失败');
                }
                return response.text();
            })
            .then(data => {
                alert(data);
            })
            .catch(error => {
                document.getElementById('loading').style.display = 'none';
                alert(error.message);
            });
        }
    </script>
</body>
</html>

3. 使用Go模板控制加载状态

// 在Go模板中动态控制
func handleForm(w http.ResponseWriter, r *http.Request) {
    data := struct {
        ShowLoading bool
        FormData    map[string]string
    }{
        ShowLoading: r.Method == "POST",
    }
    
    tmpl.ExecuteTemplate(w, "form_with_loading.html", data)
}

4. 使用Base64编码的GIF

// 直接嵌入Base64编码的GIF
const loadingGIF = `data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==`

func renderPage(w http.ResponseWriter) {
    html := fmt.Sprintf(`
        <div id="loading" style="display:none;">
            <img src="%s" alt="加载中...">
        </div>
    `, loadingGIF)
    w.Write([]byte(html))
}

5. 结合WebSocket实时更新状态

// websocket_server.go
package main

import (
    "github.com/gorilla/websocket"
    "net/http"
)

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool { return true },
}

func handleWebSocket(w http.ResponseWriter, r *http.Request) {
    conn, _ := upgrader.Upgrade(w, r, nil)
    defer conn.Close()
    
    // 发送加载状态
    conn.WriteMessage(websocket.TextMessage, []byte("loading"))
    
    // 模拟处理
    time.Sleep(2 * time.Second)
    
    // 发送完成状态
    conn.WriteMessage(websocket.TextMessage, []byte("complete"))
}

这些示例展示了在Go Web应用中实现加载状态的不同方法。实际使用时,可以根据具体需求选择合适的方式。

回到顶部