如何使用 GO (golang) 在 HTML 中嵌入 SQLX 结果

How to embed SQLX results in HTML using GO (golang)

我正在尝试使用 GO 作为后端将 Sql 查询的结果嵌入到 html table 中。要在 Go 中迭代行结果,使用 Rows.Next() 函数。这适用于打印到控制台 window,但不适用于 html table。 这是我的 Go 代码:

package main
// Database connection Code for http://play.golang.org/p/njPBsg0JjD

import (
    "net/http"
    "html/template"
    "fmt"
    "github.com/LukeMauldin/lodbc"
    "github.com/jmoiron/sqlx"
    "database/sql"
)

//declare database class
var db *sqlx.DB

type webdata struct {
    Title string
    Heading string
    GridTitle string
    ColumnHeading [9]string
    RowData [9]string
    NumOfRows *sql.Rows
}

//this is the function handler to handle '/mbconsole'
func ConsoleHandler(w http.ResponseWriter, r *http.Request) {

    //declare an instance of webdata
    var wdata webdata

    //connect to database
    //Set ODBC driver level
    lodbc.SetODBCVersion(lodbc.ODBCVersion_3)

    var err error
    //connect to a Microsoft SQL Server
    db, err = sqlx.Open("lodbc", "[connectionstring]")
    if err == nil {
        fmt.Println("Connection successful")
    }else{
        fmt.Println("SQL Connection error", err)
    }

    // Execute the queries
    rows, err := db.Query("[Select ...]")
    if err != nil {
        panic(err.Error())
    }


    // Get column names
    columns, err := rows.Columns()
    if err != nil {
        panic(err.Error())
    }


    // Make a slice for the values
    values := make([]interface{}, len(columns))

    // rows.Scan wants '[]interface{}' as an argument, so we must copy the
    // references into such a slice
    // See http://code.google.com/p/go-wiki/wiki/InterfaceSlice for details
    scanArgs := make([]interface{}, len(values))

    for i := range values {
        scanArgs[i] = &values[i]
    }
    //fill table headings, the table returns 9 columns so I just hard coded it
    for i:=0;i<9;i++ {
        wdata.ColumnHeading[i] = columns[i]
    }

    wdata.NumOfRows = rows

    // Fetch rows
    for rows.Next() {
        err = rows.Scan(scanArgs...)
        if err != nil {
            panic(err.Error())
        }
        // Print data
        for i, value := range values {
            switch value.(type) {
            case nil:
                wdata.RowData[i] = "NULL"
            case []byte:
                wdata.RowData[i] = string(value.([]byte))
            default:
                wdata.RowData[i] = fmt.Sprint(value)
            }
        }
    }

    wdata.Title = "Page Title"
    wdata.Heading = "My View"
    wdata.GridTitle = "My Grid Title"

    //get the template the data will be loaded into
    t1, err := template.ParseFiles("template.html")
    if t1 == nil {
        fmt.Println("File Not Found: ", err)
    }
    //load the template with data and display
    terr := t1.Execute(w, &wdata)
    if terr != nil {
        fmt.Println("terr: ", terr)
    }

    db = db.Unsafe()
    defer db.Close()

}


func main() {
    http.HandleFunc("/",ConsoleHandler)
}

这是我的template.html

<html>
<head><title>{{.Title}}</title></head><body>
...
<h1>{{.Heading}}</h1>
    <div id="gridviewcontainer">
    <br />
    <div id="gridtitle">
        <a href="{{.GridTitleLink}}" style="font-size:25px;">{{.GridTitle}}</a>
    </div>
    <table id="gridtable">
    <tr>{{range $ColumnIdx, $colheading := .ColumnHeading}}
    <th>{{$colheading}}</th>{{end}}</tr>
<<!---This is what is causing the issue, .NumOfRows is not a valid field, must be array, channel, pipeline, or map --> 
    {{range $index, $rowval := .NumOfRows}}
        <tr>
        {{range $rowidx, $rowdat := .RowData}}<td>{{$rowdat}}</td>{{end}}
        </tr>
        {{endfor}}
    </table>

...
</body>
</html>

我正确连接到数据库并使用 "fmt" 包我可以正确打印。但我无法弄清楚如何遍历 html 页面中返回的行数。有没有办法将 sql.Rows 转换为正确的类型或在 html 中循环设定的整数次数。

ps。 我尝试在 html 中使用 {{ $index := 3}}...{end}} 但那没有用

任何输入将不胜感激

在新行的开头,插入一个 "NewRow" 字符串作为 html 中的标志。然后在 {{range $rowidx, $rowdat :​​= .RowData}} 循环中添加一个 if 语句,该语句结束并开始一个新行 if $rowdat == "NewRow"

我使用这个变体:

func MainPageHandler(w http.ResponseWriter, r *http.Request) { 
    type User struct {
        Name1  string
        Name2  string
    }

    rows, err := database.Query("select  .......;")
    if err != nil {
        log.Println(err)
    }
    defer rows.Close()
    user_current := []User{}
    for rows.Next() {
        p := User{}
        err := rows.Scan(&p.Name1, &p.Name2 )
        if err != nil {
            fmt.Println(err)
            continue
        }
        user_current = append(user_current, p)
    }
    tmpl, _ := template.ParseFiles("main_page.html")
    tmpl.Execute(w, user_current)
}

html

<table>
     <thead><th>name1/th><th>name2</th></thead>
            {{range . }}
            <tr>
                <td>{{.Name1}}</td>
                <td>{{.Name2}}</td>
            </tr>
            {{end}}
        </table>