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

时间:2015-02-13 17:06:02

标签: html sql sql-server templates go

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

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页面中的数量。有没有办法在html中将sql.Rows转换为正确的类型或循环设置整数次。

PS。 我尝试在html中使用{{$ index:= 3}} ... {end}},但这不起作用

非常感谢任何输入

2 个答案:

答案 0 :(得分:0)

在新行的开头,插入一个“NewRow”字符串作为html中的标志。然后在{{range $ rowidx,$ rowdat:= .RowData}}循环中添加一个if语句,如果$ rowdat ==“NewRow”

结束并开始一个新行

答案 1 :(得分:0)

我使用此变体:

开始

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>