Golang中如何调用JS的WebSQL
Golang中如何调用JS的WebSQL
我正在深入学习 Go 的 "syscall/js" 包,遇到了 WebSQL,我有以下函数签名并想在 Go 中复现它:
tx.executeSql(SQLstatement, [], successCallback, errorCallback);
其中 tx 是通过 db 传递的,完整代码如下:
<script>
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) {
var len = results.rows.length, i;
msg = "<p>Found rows: " + len + "</p>";
document.querySelector('#status').innerHTML += msg;
for (i = 0; i < len; i++) {
msg = "<p><b>" + results.rows.item(i).log + "</b></p>";
document.querySelector('#status').innerHTML += msg;
}
}, null);
});
</script>
我的方法如下:
=> 为每个函数创建 js.Global() 然后 Invoke 它,所以我尝试了类似这样的代码:
package main
import "syscall/js"
var (
document js.Value
)
func init() {
document = js.Global().Get("document")
}
var openDatabase = js.Global().Get("openDatabase")
var transaction = js.Global().Get("transaction")
var executeSql = js.Global().Get("executeSql")
type DB struct{}
func (db *DB) Open(file string) {
db = openDatabase.Invoke(file, "1.0", "Test DB", 2*1024*1024)
}
func (db *DB) Query(tx string){
db.transaction.Invoke(function(tx) {
db.executeSql.Invoke(tx, [], successCallback, errorCallback);
});
}
func main() {
db := DB.Open('mydb')
db.Query('SELECT * FROM LOGS')
}
然后我卡住了,因为不知道如何管理 Callback 函数。
有什么想法吗?
更多关于Golang中如何调用JS的WebSQL的实战教程也可以访问 https://www.itying.com/category-94-b0.html
谢谢,实际上我正在尝试实现离线功能,以防连接丢失。
更多关于Golang中如何调用JS的WebSQL的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Sibert:
本地 SQLite?
我的服务器容量有限,不支持数据库,所以正在寻找浏览器内的数据库解决方案。
hyousef:
我正在尝试实现离线功能
本地 SQLite?
hyousef:
浏览器中的数据库
我所知的唯一浏览器数据库是 localStorage,并且很难从 Go 中访问它。
hyousef:
有什么想法吗?
在我看来,Go 和 JavaScript 之间的通信是一个挑战。
我的经验是,当你查询数据库时,结果必须包含在 HTML 模板中并在服务器端渲染。这就是 SSR(服务器端渲染)。我发现没有其他方式可以与网页通信(除了 WebSocket —— 也许可以)。
SSR(服务器端渲染)和 CSR(客户端渲染)各有其优点。但将它们混合起来的 SSG(静态站点生成)可能更有益。这意味着 Go 在构建时从模板渲染 HTML,而所有动态内容由 AJAX(JavaScript)提供。我连接一个由 Go 创建的 API(包含 SQL 查询),并使用 AJAX 来调用这个 API。我认为这样你就能兼得两者之长。Go 作为 API 很好,而 AJAX 则适合 REST 查询。
使用 AJAX 的 SSG 减少了页面闪烁,因为它只渲染页面的一部分。所以我的结论是使用 AJAX 与 API 通信。
这些是我的结论。希望能被证明是错误的 🙂
var url = "https://api2.go4webdev.org/test/1";
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.setRequestHeader("Accept", "application/json");
xhr.onload = function () {
if (xhr.readyState === 4) {
document.getElementById("put").innerHTML = this.responseText
}};
xhr.send();
在Go中调用WebSQL需要通过syscall/js包与JavaScript交互,正确处理回调函数是关键。以下是实现示例:
package main
import (
"syscall/js"
)
func main() {
// 获取全局对象和openDatabase函数
global := js.Global()
openDatabase := global.Get("openDatabase")
// 打开数据库
db := openDatabase.Invoke(
"mydb",
"1.0",
"Test DB",
2*1024*1024,
)
// 定义成功回调函数
successCallback := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
tx := args[0]
results := args[1]
rows := results.Get("rows")
length := rows.Get("length").Int()
statusDiv := global.Get("document").Call("querySelector", "#status")
currentHTML := statusDiv.Get("innerHTML").String()
// 添加行数信息
statusDiv.Set("innerHTML", currentHTML +
"<p>Found rows: " + js.ValueOf(length).String() + "</p>")
// 遍历结果
for i := 0; i < length; i++ {
row := rows.Call("item", i)
logValue := row.Get("log").String()
currentHTML = statusDiv.Get("innerHTML").String()
statusDiv.Set("innerHTML", currentHTML +
"<p><b>" + logValue + "</b></p>")
}
return nil
})
defer successCallback.Release()
// 定义错误回调函数
errorCallback := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// 处理错误
js.Global().Call("console", "error", args[0])
return nil
})
defer errorCallback.Release()
// 执行事务
transactionFunc := db.Get("transaction")
transactionFunc.Invoke(js.FuncOf(func(this js.Value, args []js.Value) interface{} {
tx := args[0]
// 执行SQL查询
executeSqlFunc := tx.Get("executeSql")
executeSqlFunc.Invoke(
"SELECT * FROM LOGS",
js.ValueOf([]interface{}{}),
successCallback,
errorCallback,
)
return nil
}))
// 保持程序运行
select {}
}
对于更结构化的实现,可以这样封装:
package main
import (
"syscall/js"
)
type WebSQL struct {
db js.Value
}
func NewWebSQL(name, version, desc string, size int) (*WebSQL, error) {
openDatabase := js.Global().Get("openDatabase")
db := openDatabase.Invoke(name, version, desc, size)
return &WebSQL{db: db}, nil
}
func (w *WebSQL) Query(sql string, params []interface{},
success, error js.Func) {
transactionFunc := w.db.Get("transaction")
transactionFunc.Invoke(js.FuncOf(func(this js.Value, args []js.Value) interface{} {
tx := args[0]
// 转换参数为JavaScript数组
jsParams := js.Global().Get("Array").New(len(params))
for i, param := range params {
jsParams.SetIndex(i, param)
}
executeSqlFunc := tx.Get("executeSql")
executeSqlFunc.Invoke(sql, jsParams, success, error)
return nil
}))
}
func main() {
db, _ := NewWebSQL("mydb", "1.0", "Test DB", 2*1024*1024)
success := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
results := args[1]
rows := results.Get("rows")
for i := 0; i < rows.Get("length").Int(); i++ {
row := rows.Call("item", i)
// 处理每一行数据
_ = row.Get("log").String()
}
return nil
})
defer success.Release()
error := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// 错误处理
return nil
})
defer error.Release()
db.Query("SELECT * FROM LOGS", []interface{}{}, success, error)
select {}
}
关键点:
- 使用
js.FuncOf创建Go函数作为JavaScript回调 - 通过
Get()方法获取JavaScript对象的属性和方法 - 使用
Invoke()调用JavaScript函数 - 回调函数完成后需要调用
Release()释放资源 - 参数需要通过
js.ValueOf()或直接传递JavaScript值
注意:WebSQL是已废弃的API,现代浏览器中可能不可用。在生产环境中建议考虑IndexedDB或其他存储方案。

