Golang中如何检查元素是否存在并获取其布尔值

Golang中如何检查元素是否存在并获取其布尔值 在我的代码中,我将一个结构体 ReturnedResult 发送到模板:

type ReturnedResult struct {
	Result  bool   `json:"result"`
	Message string `json:"message"`
}

我希望模板能够:

  1. 检查是否存在 Result 或为 nil
  2. 如果存在 Result,我希望检查它是 true 还是 false

因此,我写了以下代码:

{{with .Result}}
  {{if .Result}}
    <div id='foo'>
      <i class="far fa-thumbs-up"></i>If report not opened automatically, pls download from <a href={{.Message}}>here</a>
    </div>
    <script>
      url = `{{.Message}}`
      window.open(url, "_blank");
      setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
    </script>
  {{else}}
    <i class="fas fa-exclamation-triangle">{{.Message}}</i>>
    <script>
      setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
    </script>
  {{end}}
{{end}}

有时我调用模板时不带数据,如 tmpl.Execute(w, nil),有时带数据,如 tmpl.Execute(w, webReturn)

不带数据的调用工作正常,但带数据的调用不工作,不知道问题出在哪里。

如果需要,下面是我的完整代码。

// go build -ldflags "-H=windowsgui"
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"text/template"

	"github.com/zserge/lorca"
)

// ContactDetails ...
type ContactDetails struct {
	Email   string
	Subject string
	Message string
	Color1  []string
	Color2  []string
}

// ReturnedResult ...
type ReturnedResult struct {
	Result  bool   `json:"result"`
	Message string `json:"message"`
}

func index(w http.ResponseWriter, r *http.Request) {
	tmpl := template.Must(template.ParseFiles("forms.html"))
	if r.Method != http.MethodPost {
		tmpl.Execute(w, nil)
		return
	}

	r.ParseForm()
	fmt.Println(r.Form) // print information on server side.
	fmt.Println("path", r.URL.Path)
	fmt.Println("scheme", r.URL.Scheme)
	fmt.Println(r.Form["color1"][0])
	fmt.Println(r.Form["color1"][1])
	for k, v := range r.Form {
		fmt.Println("key:", k)
		fmt.Println("val:", strings.Join(v, ""))
	}
	details := ContactDetails{
		Email:   r.FormValue("email"),
		Subject: r.FormValue("subject"),
		Message: r.FormValue("message"),
		Color1:  r.Form["color1"],
		Color2:  r.Form["color2"],
	}
	fmt.Printf("Post from website! r.PostFrom = %v\n", r.PostForm)
	fmt.Printf("Details = %v\n", details)

	//r.FormValue("username")
	fmt.Println()
	// do something with details
	sheetID := "AKfycbxfMucXOzX15tfU4errRSAa9IzuTRbHzvUdRxzzeYnNA8Ynz8LJuBuaMA/exec"
	url := "https://script.google.com/macros/s/" + sheetID + "/exec"
	bytesRepresentation, err := json.Marshal(details)
	if err != nil {
		log.Fatalln(err)
	}
	resp, err := http.Post(url, "application/json", bytes.NewBuffer(bytesRepresentation))
	if err != nil {
		log.Fatalln(err)
	}
	// read all response body
	data, _ := ioutil.ReadAll(resp.Body)

	// close response body
	resp.Body.Close()

	webReturn := ReturnedResult{}
	if err := json.Unmarshal([]byte(data), &webReturn); err != nil {
		panic(err)
	}
	fmt.Println(webReturn.Message)

	webReturn.Message = strings.ReplaceAll(webReturn.Message, "&export=download", "")
	//tmpl.Execute(w, struct{ Success bool }{webReturn.Result})
	tmpl.Execute(w, webReturn)
}

func main() {
	// Start Host goroutine
	go func() {
		http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./public"))))
		http.HandleFunc("/", index)
		http.ListenAndServe(":8090", nil)
	}()

	// Start UI
	ui, err := lorca.New("http://localhost:8090/index", "", 1200, 800)
	if err != nil {
		log.Fatal(err)
	}
	defer ui.Close()

	<-ui.Done()
}

模板:

<title>Form Submittal</title>
<style>
  body {
      font-family: Ubuntu, "times new roman", times, roman, serif;
  }
</style>
<link href="http://localhost:8090/static/fontawesome-free-5.15.2-web/css/all.css" rel="stylesheet"> <!--load all styles -->
<!-- link rel="stylesheet" href="http://localhost:8090/styles/MaterialDesign-Webfont-master/css/materialdesignicons.min.css" -->

<script type="module" src="http://localhost:8090/static/node_modules/@mdi/js/mdi.js"></script>
<script type="module">
 // import {mdi-home} from "./node_modules/@mdi/js/mdi.js";
 // alert(a);
</script>
<script>
  //import { mdi-home } from '/MaterialDesign-JS-master/mdi.js';
  function deleteRow(row) {
    var i = row.parentNode.parentNode.rowIndex - 2; // this -> td -> tr // -2 because the first 2 rows are used for header
    var tbl = document.querySelector('tbody');
    if(tbl && tbl.rows.length > 1) {
      tbl.deleteRow(i); 
      Array.from(tbl.rows).forEach((row, index) => {
        row.cells[0].innerHTML = index + 1;
      });
    }
  } 

  function insRow(row) {
    var i = row.parentNode.parentNode.rowIndex - 2; // this -> td -> tr // -2 because the first 2 rows are used for header
    var tbl = document.querySelector('tbody');
    var row = document.createElement('tr');
    row.innerHTML=`
      <th></th>
      <td><input size=25 type="text" name="color1" /></td>
      <td><input size=25 type="text" name="color2" ></td>
      <td><i class="fas fa-edit" onclick="insRow(this)"></i></td>
      <td><i class="fas fa-eraser" onclick="deleteRow(this)"></i></td>
    `;
    var len = tbl.rows.length;
    row.cells[0].innerHTML = len + 1;
    tbl.insertBefore(row, tbl.children[i+1]);
    Array.from(tbl.rows).forEach((row, index) => {
      row.cells[0].innerHTML = index + 1;
    });
    //tbl.appendChild(row);
  }
</script>
<h1>Contact</h1>
Bob lives in a <span class="mdi mdi-home"></span>.

<form method="POST">
    <label>Email:</label><br />
    <input type="text" name="email"><br />
    <label>Subject:</label><br />
    <input type="text" name="subject"><br />
    <label>Message:</label><br />
    <textarea name="message"></textarea><br />

    <table>
      <caption>Monthly savings</caption>
      <thead>
        <tr>
          <th colspan="5">The table header</th>
        </tr>
        <tr>
          <th>SN</td>
          <th>PO number</td>
          <th>PO invoice value</td>
          <th colspan="2">Action</td>
        </tr>
      </thead>
      <tbody >
        <tr>
          <th>1</th>
          <td><input size=25 type="text" name="color1" /></td>
          <td><input size=25 type="text" name="color2" /></td>
          <td colspan="2"><i class="fas fa-edit" onclick="insRow(this)"></i></td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <th colspan="5">The table footer</th>
        </tr>
      </tfoot>
    </table>

   <input type="submit">
</form>
{{with .Message}}
  {{if .Result}}
    <div id='foo'>
      <i class="far fa-thumbs-up"></i>If report not opened automatically, pls download from <a href={{.Message}}>here</a>
    </div>
    <script>
      url = `{{.Message}}`
      window.open(url, "_blank");
      setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
    </script>
  {{else}}
    <i class="fas fa-exclamation-triangle">{{.Message}}</i>>
    <script>
      setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
    </script>
  {{end}}
{{end}}

更多关于Golang中如何检查元素是否存在并获取其布尔值的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

检查是否存在 Result 或 nil

Resultbool 类型,因此它总是 truefalse。如果你希望它也可以是“可空的”,你需要将其设为 *bool 类型。

如果存在 Result,我想检查它是 true 还是 false

结构体将始终包含 Result,每个属性始终可用。你可以从 JSON 对象中省略 result 键,如果我没记错的话,解析 JSON 将会失败。如果你希望 JSON 中的这个键是可选的,请使用 *bool

更多关于Golang中如何检查元素是否存在并获取其布尔值的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go模板中检查元素是否存在并获取布尔值,你的代码存在几个关键问题。主要问题是模板逻辑错误和字段访问方式不正确。

以下是修正后的模板代码:

{{if .}}
  {{if .Result}}
    <div id='foo'>
      <i class="far fa-thumbs-up"></i>If report not opened automatically, pls download from <a href="{{.Message}}">here</a>
    </div>
    <script>
      url = `{{.Message}}`;
      window.open(url, "_blank");
      setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
    </script>
  {{else}}
    <i class="fas fa-exclamation-triangle">{{.Message}}</i>
    <script>
      setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
    </script>
  {{end}}
{{end}}

或者使用更简洁的版本:

{{if and . .Result}}
  <div id='foo'>
    <i class="far fa-thumbs-up"></i>If report not opened automatically, pls download from <a href="{{.Message}}">here</a>
  </div>
  <script>
    url = `{{.Message}}`;
    window.open(url, "_blank");
    setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
  </script>
{{else if .}}
  <i class="fas fa-exclamation-triangle">{{.Message}}</i>
  <script>
    setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
  </script>
{{end}}

问题分析:

  1. {{with .Result}} 错误:当传入 nil 时,.Result 会报错。应该先检查整个对象是否存在。
  2. 字段访问错误:在 {{with .Result}} 块内,. 已经指向 .Result 字段(布尔值),而不是 ReturnedResult 结构体,所以 .Result.Message 访问会失败。

修正后的逻辑:

  • {{if .}} 检查传入的数据是否为 nil
  • {{if .Result}} 直接访问 Result 字段的布尔值
  • 在模板中正确使用 .Message 字段

示例代码演示:

// 测试模板逻辑
func testTemplate() {
    tmpl := `{{if .}}{{if .Result}}Result is true: {{.Message}}{{else}}Result is false: {{.Message}}{{end}}{{else}}No data{{end}}`
    
    t := template.Must(template.New("test").Parse(tmpl))
    
    // 测试1: 传入nil
    t.Execute(os.Stdout, nil) // 输出: No data
    
    // 测试2: Result为true
    data1 := ReturnedResult{Result: true, Message: "Success"}
    t.Execute(os.Stdout, data1) // 输出: Result is true: Success
    
    // 测试3: Result为false
    data2 := ReturnedResult{Result: false, Message: "Error"}
    t.Execute(os.Stdout, data2) // 输出: Result is false: Error
}

这样修改后,无论是 tmpl.Execute(w, nil) 还是 tmpl.Execute(w, webReturn) 都能正常工作。

回到顶部