package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
// 验证用户名和密码
username := r.FormValue("username")
password := r.FormValue("password")
if username == "admin" && password == "admin123" {
// 设置记住我Cookie
cookie := &http.Cookie{
Name: "remember_me",
Value: "1",
Expires: time.Now().Add(30 * 24 * time.Hour),
}
http.SetCookie(w, cookie)
fmt.Fprint(w, "Login successful.")
return
}
http.Error(w, "Invalid username or password", http.StatusUnauthorized)
})
http.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) {
// 检查记住我Cookie
cookie, err := r.Cookie("remember_me")
if err == nil && cookie.Value == "1" {
fmt.Fprint(w, "Welcome back!")
return
}
// 显示登录页面
fmt.Fprint(w, "Please login.")
})
http.ListenAndServe(":8080", nil)
}
代码整体解读:
代码创建了一个简单的web服务器,然后具有基础的登录功能和使用Cookie实现的记住我功能。
由三个代码组成,大体是两个注册服务,最好一个启动服务。第一个实现了登录处理,第二个实现了记住我处理。
代码详细解读:
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
// 验证用户名和密码
username := r.FormValue("username")
password := r.FormValue("password")
if username == "admin" && password == "admin123" {
// 设置记住我Cookie
cookie := &http.Cookie{
Name: "remember_me",
Value: "1",
Expires: time.Now().Add(30 * 24 * time.Hour),
}
http.SetCookie(w, cookie)
fmt.Fprint(w, "Login successful.")
return
}
username := r.FormValue(“username”)
password := r.FormValue(“password”)
从请求中拿到客户端发来的登录信息:用户名和密码
if username == "admin" && password == "admin123" {
// 设置记住我Cookie
cookie := &http.Cookie{
Name: "remember_me",
Value: "1",
Expires: time.Now().Add(30 * 24 * time.Hour),
}
http.SetCookie(w, cookie)
fmt.Fprint(w, "Login successful.")
return
}
随后负责对用户和密码的验证,如果匹配就进行下一步,否则就返回错误信息。
匹配成功:
先实例化了一个Cookie对象,这个对象就对有需要的字段进行了赋值,然后添加到响应中去,添加的方法就是用http.SetCookie(),最后打印信息。结束函数。这样就完成了对客户请求进行响应的适合把用户的Cookie发送给客户端。
第二个注册函数
http.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) {
// 检查记住我Cookie
cookie, err := r.Cookie("remember_me")
if err == nil && cookie.Value == "1" {
fmt.Fprint(w, "Welcome back!")
return
}
// 显示登录页面
fmt.Fprint(w, "Please login.")
})
这个是针对访问/home这个界面的,如过访问主页,那就会调用这个处理函数。这个处理函数会找到请求中remember_me记住我的Cookie,如果这个Cookie的值为1,那就表示用户之前选择了记住我,向用户发送欢迎。如果没找到cookie,那就显示请登录。
最后一个函数就是启动服务器监听端口。
最后总结:创建了两个路由/login和/home,在用户登录成功时,我们通过http.Cookie结构体的Expires属性设置一个长期有效的Cookie,并使用http.SetCookie函数将其添加到响应中,下次用户访问/home时,通过http.Request的Cookie函数,获取Cookie,并检查Cookie的值是否为1,如果是则表示用户已经登录,否则需要显示登录界面。
购物车功能指的是用户在网站上选择商品后,将这些商品保存在购物车中,方便用户后续进行结算或继续购物。以下是一个Cookie实现购物车功能的实例。
package main
import (
"fmt"
"net/http"
"strconv"
"strings"
)
func main() {
http.HandleFunc("/add-to-cart", func(w http.ResponseWriter, r *http.Request) {
// 获取商品ID和数量
itemID := r.FormValue("item_id")
quantity, _ := strconv.Atoi(r.FormValue("quantity"))
// 获取购物车Cookie
cookie, err := r.Cookie("cart")
if err == http.ErrNoCookie {
// 如果没有购物车Cookie,则创建一个新的购物车Cookie
cookie = &http.Cookie{
Name: "cart",
Value: "",
}
}
// 将商品添加到购物车
cart := parseCart(cookie.Value)
cart[itemID] += quantity
// 更新购物车Cookie
cookie.Value = formatCart(cart)
http.SetCookie(w, cookie)
fmt.Fprint(w, "Item added to cart.")
})
http.HandleFunc("/view-cart", func(w http.ResponseWriter, r *http.Request) {
// 获取购物车Cookie
cookie, err := r.Cookie("cart")
if err == http.ErrNoCookie {
// 如果没有购物车Cookie,则显示空购物车
fmt.Fprint(w, "Your cart is empty.")
return
}
// 显示购物车中的商品
cart := parseCart(cookie.Value)
if len(cart) == 0 {
fmt.Fprint(w, "Your cart is empty.")
return
}
fmt.Fprintln(w, "Your cart:")
for itemID, quantity := range cart {
fmt.Fprintf(w, "- Item #%s: %d\n", itemID, quantity)
}
})
http.ListenAndServe(":8080", nil)
}
// 将字符串按分隔符分割为切片
func split(s, sep string) []string {
return strings.Split(s, sep)
}
// 将切片按分隔符拼接为字符串
func join(s []string, sep string) string {
return strings.Join(s, sep)
}
// 将购物车map格式化为字符串
func formatCart(cart map[string]int) string {
items := make([]string, 0, len(cart))
for itemID, quantity := range cart {
items = append(items, itemID+":"+strconv.Itoa(quantity))
}
return join(items, ",") // 修改分隔符为逗号 ","
}
// 将购物车字符串解析为map
func parseCart(cartStr string) map[string]int {
cart := make(map[string]int)
for _, item := range split(cartStr, ",") { // 修改分隔符为逗号 ","
if item == "" {
continue
}
parts := split(item, ":")
if len(parts) != 2 {
continue
}
id := parts[0]
quantity, err := strconv.Atoi(parts[1])
if err != nil {
continue
}
cart[id] += quantity
}
return cart
}
这个代码看着很复杂,我来进行拆分
按函数来看就可以看出功能了
首先就是下面这些不在main函数里面的,这些都是一些辅助函数(也就是工具)
主要的逻辑在main函数里面
main函数解读:
可以看到由两个handlefunc服务注册函数和一个启动服务器函数组成。
注册函数1:实现的是添加到购物车功能。
先解读里面用到的函数:
itemID := r.FormValue(“item_id”)
我再解读这个函数(因为我对Form的了解也挺少的,这个是请求结构里面的一个重要字段)
Form代表了HTTP请求中的表单数去,当一个HTTP请求是POST或PUT方法,并且内容类型是application/x-www-form-urlencoded" 或 "multipart/form-data时,表单数据被包含在请求体中。FormValue 方法是 http.Request 的一个便利方法,用于从表单数据中提取指定字段的值。当你调用 r.FormValue(“item_id”),这个方法将查找名为 “item_id” 的表单字段,并返回其值作为字符串。
这里举个例子:
假如有个html表单,用户可以在其中输入商品ID和数量:
<form action="/add-to-cart" method="post">
<input type="text" name="item_id" />
<input type="number" name="quantity" />
<input type="submit" value="Add to Cart" />
</form>
当用户填写此表单并提交时,表单数据(包括 item_id 和 quantity 字段)会被发送到服务器的 “/add-to-cart” 路径。在服务器端,
所以在服务器端使用
r.FormValue(“item_id”) 将获取用户输入的 item_id 字段的值。
注意这个函数的返回值是字符串。
quantity, _ := strconv.Atoi(r.FormValue(“quantity”))
这里时先用上面这个方法获取到了quantity的这个字段的值,这个字段表示的时添加到购物车的商品数量。
然后strconv.Atoi函数将字符串转换成了整数,这是strconv包的一个函数,Atoi是ASCII to integer的缩写。最终这个函数返回值是转换后的整数和一个error。
cookie, err := r.Cookie(“cart”)
获取购物车的Cookie,下面有个错误判断,如果cart的Cookie不存在,那么就会新创建一个购物车Cookie。
cart := parseCart(cookie.Value)
cart[itemID] += quantity
先看这个parseCart(cookie.Value)
这个函数的逻辑是解析一个代表购物车内容的字符串,然后将其转为一个map,key是商品ID,值是商品数量。
内部逻辑:
1.创建空购物车,首先创建一个空map,名为cart,用于存储商品ID和对于的数量。
2.遍历购物车项,使用split函数以,为分隔符将cartStr字符串分割成多个购物车项,每个项的格式预期为"itemID:quantity"
3.解析每个购物车项:
分割开后的项item,如果是空字符串,跳过当前迭代
再次使用split函数,这次以:为分隔符将项分割成两部分,分别是商品ID和数量
如果分割后不是两部分,说明格式不正确,跳过当前迭代。
4.使用strconv.Atoi将数量部分转换成整数。如果转换过程中错误就跳过迭代。在map中累加对于商品ID的数量。
5.返回购物车map,最后返回包含所有有效购物车项的map。
该函数总结:有效地从简单字符串格式中提取出了复杂的数据结构,使得购物车的内容可以在Cookie中以字符串形式存储和传输
cookie.Value = formatCart(cart)
http.SetCookie(w, cookie)
说说上面这个函数
这个函数实现了将购物车的内容(map[string]int)类型标识的cart格式化为一个字符串,然后下面这个函数将这个字符串赋值给cookie的value字段,这就完成了购物车的数据更新。
函数内部:这个函数内部做了将购物车map作为输入,然后map的键是商品ID,value是对于的数量,然后将每个商品ID和它的数量转换成"itemID:quantity"格式的字符串,并将这些字符串用,连接。最终形成一个单一的字符串作为返回值。然后这个拼接成的字符串就赋值给了cookie.Value使得购物车的内容可以存储在一个HTTP的Cookie中。这样当客户端发送请求时,服务器能够通过解析这个Cookie来重建用户的购物车状态。
第二个注册函数:
这个函数定义了查看购物车路径请求的响应。用于显示购物车中的商品。
1.先获取了购物车的Cookie,如果没有找到购物车的Cookie,则代表购物车为空,返回给客户端信息,”你的购物车为空“。
2.解析购物车的内容,就是将购物车对应的Cookie的内容全转成购物车map,其中键是商品id,value是数量。
3.检查购物车是否为空,检查cart的长度是0就代表购物车空,再次发送你的购物车为空的信息。
4.遍历这个cart就是显示购物车的内容,然后并把这个内容发送回客户的响应。
最后启动服务器。
总结过程:
用户访问/add-to-Cart路由时,会获取商品的ID和数量,然后通过Request的Cookie函数,获取购物车的Cookie,如果没有购物车那就创建一个新的购物车Cookie,然后将商品添加到购物车中,更新购物车,最后通过setCookie将购物车的Cookie协会客户端中。
当用户访问/view-cart路由时,会通过Request的Cookie函数获取购物车的Cookie,如果没有购物车,则显示购物车为空,发否则解析购物车Cookie并显示购物车中的商品。
购物车的数据时一个字符串,格式为"item_id1:quantity1;item_id2:quantity2;…其中前者标识商品ID后者标识商品数量,为了方便解析和格式化购物车数据,搞了很多辅助函数。
什么是CSRF?
在Web应用中,CSRF攻击是一种常见的威胁,攻击者利用用户登录的登录状态伪造请求来执行未授权的操作。常见的CSRF攻击恶意修改用户资料、发起转账、删除数据等。
为了防御CSRF攻击,我们可以在Cookie中添加CSRF Token,并在每次请求中验证Token的而正确性。
1.在登录成功后生成一个CSRF Token并将其保存在Cookie中
func loginHandler(w http.ResponseWriter, r *http.Request) {
// 验证用户名和密码...
// 生成 CSRF Token
csrfToken := generateCSRFToken()
// 将 CSRF Token 保存到 Cookie 中
http.SetCookie(w, &http.Cookie{
Name: "csrf_token",
Value: csrfToken,
HttpOnly: true,
Secure: true,
})
// 重定向到首页
http.Redirect(w, r, "/", http.StatusFound)
}
func editProfileHandler(w http.ResponseWriter, r *http.Request) {
// 获取用户提交的数据...
// 验证 CSRF Token 的正确性
csrfToken := r.FormValue("csrf_token")
if csrfToken != getCSRFTokenFromCookie(r) {
http.Error(w, "Invalid CSRF Token", http.StatusForbidden)
return
}
// 更新用户资料...
// 返回结果页面...
}
其中getCSRF…是一个复杂函数,用于从请求中获取CSRF Token的值
func getCSRFTokenFromCookie(r *http.Request) string {
cookie, err := r.Cookie("csrf_token")
if err != nil {
return ""
}
return cookie.Value
}
这个示例中我们将CSRF Token保存在Cookie中,并使用HTTPOnly和Secure选项来增强安全性,每次请求都会验证用户提交的CSRF Token和Cookie中保存的CSRF Token是否一致性来判断合法性。
在Web应用中,Session用于存储用户的会话状态,包括用户登录状态、购物车数据、表单数据等。Session通常使用Cookie来实现,在服务端保存Session数据,并在客户端保存Session ID。客户端在每次请求中通过Cookie将Session ID发送到服务端,服务端根据Session ID获取对应的Session数据。
go语言中要使用第三方库来实现Session的功能,来看示例:
1.导入这个第三方包
import (
"github.com/gorilla/sessions"
)
2.创建一个Session存储器
store := sessions.NewCookieStore([]byte("my-secret-key"))
参数是加密密钥,用来保护session数据的安全性。
3.在处理请求的函数中使用Session
func myHandler(w http.ResponseWriter, r *http.Request) {
// 获取Session
session, err := store.Get(r, "my-session")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 操作Session
session.Values["foo"] = "bar"
session.Save(r, w)
// 返回响应
fmt.Fprintf(w, "Session value set to %s", session.Values["foo"])
}
使用store.Get函数来获取请求中名为my-session的Session,然后通过session的方法来操作Session的数据,在操作完之后,session.Save(r, w)通过这个函数写回到Cookie中,并通过http.ResponseWriter将响应发送给客户端。
在实际应用中Session还有很多的字段。可以用来操作。比如可以设置Session的过期时间,Session的域名和路径、Session的安全选项等。
在go语言中,使用session进行用户身份验证通常需要以下步骤:
1.创建一个session:当用户成功登录时,可以创建一个session来保存用户信息和状态。这通常涉及到生成一个唯一的会话ID,并将该ID存储在一个cookie中。
2.检查session:在处理每个请求时,应该检查cookie中是否存在会话ID。如果存在,就可以从session存储中读取用户信息和状态。如果不存在,就需要将用户重定向到登录页面。
3.验证用户:在处理请求时,需要验证session中存储的用户信息,以确保用户已经登录并具有适当的访问权限。如果验证失败,则需要将用户重定向到登录页面。
示例:
package main
import (
"net/http"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
var store = sessions.NewCookieStore([]byte("secret-key"))
func main() {
r := mux.NewRouter()
r.HandleFunc("/", homeHandler)
r.HandleFunc("/login", loginHandler).Methods("POST")
r.HandleFunc("/logout", logoutHandler)
http.ListenAndServe(":8080", r)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-id")
// 检查是否存在会话ID
if session.Values["authenticated"] != true {
http.Redirect(w, r, "/login", 302)
return
}
// 在此处处理受保护的页面
}
func loginHandler(w http.ResponseWriter, r *http.Request) {
// 在此处执行用户验证
// 验证成功,创建session
session, _ := store.Get(r, "session-id")
session.Values["authenticated"] = true
session.Save(r, w)
// 重定向到首页
http.Redirect(w, r, "/", 302)
}
func logoutHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-id")
session.Values["authenticated"] = false
session.Save(r, w)
// 重定向到登录页面
http.Redirect(w, r, "/login", 302)
}
在上述示例中,当用户登录时,我们创建了一个session,将“authenticated”值设置为true,并将session ID保存在cookie中。在处理每个请求时,我们检查cookie中是否存在session ID。如果存在,我们从session存储中读取“authenticated”值。如果该值为true,表示用户已经登录,可以访问受保护的页面。如果该值为false或不存在,我们将用户重定向到登录页面。当用户注销时,我们将“authenticated”值设置为false,并将session ID从cookie中删除。
在Go语言中,使用session进行状态管理通常需要以下步骤:
1.创建一个session:在用户开始会话时,可以创建一个session来保存会话状态。这通常涉及到生成一个唯一的会话ID,并将该ID存储在一个cookie中。
2.存储状态:在处理每个请求时,可以将任何需要跟踪的状态信息存储在session中。这可以通过向session.Values中添加键值对来完成。
3.检索状态:在处理请求时,可以从session.Values中检索保存的状态信息。
一个示例:Go语言中使用Session进行状态管理
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
var store = sessions.NewCookieStore([]byte("secret-key"))
func main() {
r := mux.NewRouter()
r.HandleFunc("/", homeHandler)
r.HandleFunc("/add", addHandler).Methods("POST")
http.ListenAndServe(":8080", r)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-id")
// 检索保存的状态
count := session.Values["count"]
// 如果状态不存在,初始化为0
if count == nil {
count = 0
}
// 显示状态信息
fmt.Fprintf(w, "Count: %d\n", count)
// 将状态增加1
count = count.(int) + 1
// 存储新的状态
session.Values["count"] = count
session.Save(r, w)
}
func addHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-id")
// 检索保存的状态
count := session.Values["count"]
// 如果状态不存在,初始化为0
if count == nil {
count = 0
}
// 解析请求中的参数
r.ParseForm()
value := r.Form.Get("value")
// 将参数转换为数字
num, err := strconv.Atoi(value)
if err != nil {
http.Error(w, "Invalid input", http.StatusBadRequest)
return
}
// 将状态增加传入的值
count = count.(int) + num
// 存储新的状态
session.Values["count"] = count
session.Save(r, w)
// 重定向到首页
http.Redirect(w, r, "/", 302)
}
在上述示例中,我们使用session来存储一个计数器的状态。在处理每个请求时,我们从session.Values中检索计数器的值。如果该值不存在,我们将其初始化为0。在首页中,我们显示计数器的值,并将其增加1。在addHandler中,我们从请求参数中获取一个值,并将其添加到计数器的值中。最后,我们将新的计数器值保存到session.Values中,并重定向到首页。
在Go语言中实现在线人数功能,可以用session来记录在线用户
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
var store = sessions.NewCookieStore([]byte("secret-key"))
func main() {
r := mux.NewRouter()
r.HandleFunc("/", homeHandler)
http.ListenAndServe(":8080", r)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-id")
// 检查session中是否有userID键
if session.Values["userID"] == nil {
// 如果没有,说明用户是新的,将userID存储在session中
session.Values["userID"] = "user-" + fmt.Sprint(time.Now().UnixNano())
session.Save(r, w)
}
// 获取当前在线用户数
onlineCount := getOnlineCount()
// 显示在线用户数
fmt.Fprintf(w, "Online users: %d", onlineCount)
}
func getOnlineCount() int {
// 遍历所有session,统计在线用户数
count := 0
store := sessions.NewFilesystemStore("", []byte("secret-key"))
store.Walk(func(sess *sessions.Session, err error) error {
if err != nil {
return err
}
if sess.Values["userID"] != nil {
count++
}
return nil
})
return count
}
在上述代码中,我们定义了一个名为getOnlineCount的函数,该函数用于遍历所有session并计算在线用户数。在homeHandler中,我们检查session中是否有一个名为userID的键。如果没有,说明用户是新的,我们将一个唯一的userID存储在session中。然后我们调用getOnlineCount函数获取当前在线用户数,并将其显示给用户。
需要注意的是,在实际生产环境中,这种方式可能会有性能问题。在处理每个请求时遍历所有session会很慢,因此我们应该使用更高效的方法来记录在线用户,例如使用Redis或Memcached等内存数据库来存储session信息。
在go语言中可以使用session来实现购物车功能。以下是一个基本的购物车应用实例
package main
import (
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
var store = sessions.NewCookieStore([]byte("secret-key"))
type Product struct {
Name string
Price float64
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/", homeHandler)
r.HandleFunc("/add-to-cart/{productID}", addToCartHandler)
r.HandleFunc("/cart", cartHandler)
http.ListenAndServe(":8080", r)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
products := []Product{
{Name: "Product 1", Price: 10.0},
{Name: "Product 2", Price: 20.0},
{Name: "Product 3", Price: 30.0},
}
// 显示商品列表和添加到购物车的链接
for _, product := range products {
fmt.Fprintf(w, "%s - $%.2f Add to Cart
", product.Name, product.Price, productID)
}
}
func addToCartHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-id")
productID, _ := strconv.Atoi(mux.Vars(r)["productID"])
cart, ok := session.Values["cart"].(map[int]int)
if !ok {
cart = make(map[int]int)
}
cart[productID]++
session.Values["cart"] = cart
session.Save(r, w)
http.Redirect(w, r, "/cart", http.StatusSeeOther)
}
func cartHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session-id")
// 检查session中是否有cart键
if session.Values["cart"] == nil {
// 如果没有,说明购物车为空
fmt.Fprint(w, "Your cart is empty.")
return
}
// 显示购物车中的商品和数量
cart := session.Values["cart"].(map[int]int)
fmt.Fprintf(w, "Your cart:
")
for productID, quantity := range cart {
product := getProductByID(productID)
fmt.Fprintf(w, "%s - $%.2f x %d
", product.Name, product.Price, quantity)
}
}
func getProductByID(productID int) Product {
// 实际应用中,此处应从数据库中获取商品信息
products := []Product{
{Name: "Product 1", Price: 10.0},
{Name: "Product 2", Price: 20.0},
{Name: "Product 3", Price: 30.0},
}
for _, product := range products {
if productID == getProductID(product) {
return product
}
}
return Product{}
}
func getProductID(product Product) int {
// 实际应用中,此处应根据商品信息生成唯一的ID
return len(product.Name)
}
上述代码是一个使用Go语言实现的简单购物车应用程序,使用session来管理购物车状态。这个购物车应用程序由三个处理程序组成:
1.homeHandler:在该处理程序中,我们显示了商品列表和添加到购物车的链接,用于让用户选择商品并将其添加到购物车中。
2.addToCartHandler:在该处理程序中,我们使用session来管理购物车状态。我们从URL中获取所选商品的ID,将其添加到session的购物车中,并重定向到购物车页面。
3.cartHandler:在该处理程序中,我们从session中获取购物车状态,然后显示购物车中的商品和数量。
购物车的状态是通过session来管理的。我们使用gorilla/sessions包创建了一个新的CookieStore实例,并将其用于存储和读取session中的数据。在addToCartHandler中,我们将购物车状态保存到session.Values[“cart”]中,并将其保存到cookie中。在cartHandler中,我们从session.Values[“cart”]中获取购物车状态,并显示其中的商品和数量。
package main
import (
"fmt"
"net/http"
"github.com/gorilla/sessions"
)
// 创建session存储实例,使用随机生成的密钥进行加密
var store = sessions.NewCookieStore([]byte("secret-key"))
func main() {
http.HandleFunc("/", indexHandler)
http.HandleFunc("/setcolor", setColorHandler)
http.HandleFunc("/setfont", setFontHandler)
http.ListenAndServe(":8080", nil)
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
// 从session中获取用户的颜色和字体设置
session, _ := store.Get(r, "user-settings")
color := session.Values["color"]
font := session.Values["font"]
// 显示用户的颜色和字体设置
fmt.Fprintf(w, "Your color is %s and your font is %s", color, font)
// 显示用户设置的表单
fmt.Fprintln(w, `
`)
}
func setColorHandler(w http.ResponseWriter, r *http.Request) {
// 获取用户设置的颜色值
color := r.FormValue("color")
// 将颜色设置保存到session中
session, _ := store.Get(r, "user-settings")
session.Values["color"] = color
session.Save(r, w)
// 重定向到首页
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func setFontHandler(w http.ResponseWriter, r *http.Request) {
// 获取用户设置的字体
font := r.FormValue("font")
// 将字体设置保存到session中
session, _ := store.Get(r, "user-settings")
session.Values["font"] = font
session.Save(r, w)
// 重定向到首页
http.Redirect(w, r, "/", http.StatusSeeOther)
}
这个应用程序有一个主页,显示用户的颜色和字体设置,并允许用户设置它们。当用户点击“Set Color”或“Set Font”按钮时,应用程序将用户设置保存到session中,并重定向到主页以显示新的设置。
在这个应用程序中,我们使用了gorilla/sessions包来创建一个新的CookieStore实例,并将其用于存储和读取session中的数据。我们将session的名称设置为“user-settings”,并将其传递给store.Get()和session.Save()方法,以便在处理程序之间共享session数据。
在indexHandler中,我们使用session.Values[“color”]和session.Values[“font”]从session中获取用户设置的颜色和字体,并将它们显示在网页上。我们还显示了一个表单,用于允许用户设置它们的颜色、字体。