如何使用 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>
我正在尝试使用 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>