我是 Go 语言 (Golang) 的新手,我正在编写一个基于 Web 的应用程序。我想使用会话变量,例如 PHP 中的那种(从一页到下一页可用的变量,并且对于用户会话是唯一的)。Go中有类似的东西吗?如果没有,我将如何自己实施它们?或者有什么替代方法?
3 回答
如果您只需要没有完整的 Web 工具包的会话支持,这是一个替代方案。
这是另一种选择(披露:我是作者):
https://github.com/icza/session
引用其文档:
该软件包提供了易于使用、可扩展且安全的会话实施和管理。可以在 godoc.org 中找到包文档:
https://godoc.org/github.com/icza/session
这“只是”一个 HTTP 会话实现和管理,您可以按原样使用它,也可以与任何现有的 Go web 工具包和框架一起使用。
概述
包中有 3 个主要参与者:
Session
是(HTTP)会话接口。我们可以使用它来存储和从中检索常量和变量属性。Store
是一个会话存储接口,负责存储会话并使它们可以在服务器端通过它们的 ID 进行检索。Manager
是一个会话管理器接口,负责Session
从(传入的)HTTP 请求中获取 a,并将 a 添加Session
到 HTTP 响应以让客户端知道会话。AManager
有一个支持Store
,负责管理Session
服务器端的值。
这个包的播放器由接口表示,并为所有这些播放器提供了各种实现。您不受所提供的实现的约束,请随时为任何玩家提供您自己的实现。
用法
用法再简单不过了。要获取与http.Request关联的当前会话:
sess := session.Get(r)
if sess == nil {
// No session (yet)
} else {
// We have a session, use it
}
要创建一个新会话(例如成功登录)并将其添加到http.ResponseWriter(让客户端知道该会话):
sess := session.NewSession()
session.Add(sess, w)
让我们看看更高级的会话创建:让我们提供一个常量属性(会话的生命周期)和一个初始的可变属性:
sess := session.NewSessionOptions(&session.SessOptions{
CAttrs: map[string]interface{}{"UserName": userName},
Attrs: map[string]interface{}{"Count": 1},
})
并访问这些属性并更改 的值"Count"
:
userName := sess.CAttr("UserName")
count := sess.Attr("Count").(int) // Type assertion, you might wanna check if it succeeds
sess.SetAttr("Count", count+1) // Increment count
(当然,变量属性也可以在以后添加Session.SetAttr()
,而不仅仅是在会话创建时。)
要删除会话(例如注销时):
session.Remove(sess, w)
查看会话演示应用程序,它显示了所有这些操作。
谷歌应用引擎支持
该软件包提供对 Google App Engine (GAE) 平台的支持。
文档不包括它(由于+build appengine
构建约束),但它是:gae_memcache_store.go
该实现将会话存储在 Memcache 中,并将会话保存到 Datastore 作为备份,以防数据从 Memcache 中删除。此行为是可选的,可以完全禁用 Datastore。您还可以选择是同步(在同一个 goroutine 中)还是异步(在另一个 goroutine 中)保存到 Datastore,从而缩短响应时间。
我们可以使用NewMemcacheStore()
和NewMemcacheStoreOptions()
函数来创建一个会话存储实现,它将会话存储在 GAE 的 Memcache 中。需要注意的是,由于访问 Memcache 依赖于绑定到 的 Appengine Context http.Request
,因此返回的 Store 只能用于请求的生命周期!请注意,当 Store 关闭时,Store 会自动“刷新”从中访问的会话,因此在请求结束时关闭 Store 非常重要;这通常通过关闭您将存储传递到的会话管理器来完成(最好使用 defer 语句)。
所以在每个请求处理中,我们必须使用新的 Store 创建一个新的会话管理器,我们可以使用会话管理器来执行与会话相关的任务,如下所示:
ctx := appengine.NewContext(r)
sessmgr := session.NewCookieManager(session.NewMemcacheStore(ctx))
defer sessmgr.Close() // This will ensure changes made to the session are auto-saved
// in Memcache (and optionally in the Datastore).
sess := sessmgr.Get(r) // Get current session
if sess != nil {
// Session exists, do something with it.
ctx.Infof("Count: %v", sess.Attr("Count"))
} else {
// No session yet, let's create one and add it:
sess = session.NewSession()
sess.SetAttr("Count", 1)
sessmgr.Add(sess, w)
}
过期的会话不会自动从数据存储中删除。为了删除过期的会话,包提供了一个PurgeExpiredSessFromDSFunc()
返回http.HandlerFunc
. 建议将返回的处理函数注册到一个路径,然后可以将其定义为定期调用的 cron 作业,例如每 30 分钟左右(您的选择)。由于 cron 处理程序可能运行长达 10 分钟,因此返回的处理程序将在 8 分钟处停止以安全完成,即使有更多过期、未删除的会话也是如此。可以这样注册:
http.HandleFunc("/demo/purge", session.PurgeExpiredSessFromDSFunc(""))
查看显示如何使用它的 GAE 会话演示应用程序。 演示的cron.yaml文件显示了如何定义 cron 作业以清除过期会话。
查看GAE 会话演示应用程序,它展示了如何在实际中使用它。