golang网络编程day5

golang网络编程day5

  • golang cookie实现记住我功能
  • golang cookie实现购物车功能
  • golang cookie CSRF防御应用
  • golang session
  • golang session 用户身份验证应用
  • golang session应用程序中的状态管理
  • golang实现在线人数统计
  • golang session购物车应用
  • golang session用户个性化设置应用

golang实现记住我功能

package mainimport ("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" {// 设置记住我Cookiecookie := &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) {// 检查记住我Cookiecookie, 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" {// 设置记住我Cookiecookie := &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" {// 设置记住我Cookiecookie := &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) {// 检查记住我Cookiecookie, 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,如果是则表示用户已经登录,否则需要显示登录界面。


golang cookie实现购物车功能

购物车功能指的是用户在网站上选择商品后,将这些商品保存在购物车中,方便用户后续进行结算或继续购物。以下是一个Cookie实现购物车功能的实例。

package mainimport ("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"))// 获取购物车Cookiecookie, err := r.Cookie("cart")if err == http.ErrNoCookie {// 如果没有购物车Cookie,则创建一个新的购物车Cookiecookie = &http.Cookie{Name:  "cart",Value: "",}}// 将商品添加到购物车cart := parseCart(cookie.Value)cart[itemID] += quantity// 更新购物车Cookiecookie.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) {// 获取购物车Cookiecookie, 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后者标识商品数量,为了方便解析和格式化购物车数据,搞了很多辅助函数。


golang cookie CSRF防御应用

什么是CSRF?
在Web应用中,CSRF攻击是一种常见的威胁,攻击者利用用户登录的登录状态伪造请求来执行未授权的操作。常见的CSRF攻击恶意修改用户资料、发起转账、删除数据等。

为了防御CSRF攻击,我们可以在Cookie中添加CSRF Token,并在每次请求中验证Token的而正确性。

1.在登录成功后生成一个CSRF Token并将其保存在Cookie中

func loginHandler(w http.ResponseWriter, r *http.Request) {// 验证用户名和密码...// 生成 CSRF TokencsrfToken := generateCSRFToken()// 将 CSRF Token 保存到 Cookie 中http.SetCookie(w, &http.Cookie{Name:     "csrf_token",Value:    csrfToken,HttpOnly: true,Secure:   true,})// 重定向到首页http.Redirect(w, r, "/", http.StatusFound)
}
  1. 在每次请求中验证CSRF Token的正确性:
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是否一致性来判断合法性。


golang session

在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) {// 获取Sessionsession, err := store.Get(r, "my-session")if err != nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}// 操作Sessionsession.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的安全选项等。


golang session 用户身份验证应用

在go语言中,使用session进行用户身份验证通常需要以下步骤:
1.创建一个session:当用户成功登录时,可以创建一个session来保存用户信息和状态。这通常涉及到生成一个唯一的会话ID,并将该ID存储在一个cookie中。
2.检查session:在处理每个请求时,应该检查cookie中是否存在会话ID。如果存在,就可以从session存储中读取用户信息和状态。如果不存在,就需要将用户重定向到登录页面。
3.验证用户:在处理请求时,需要验证session中存储的用户信息,以确保用户已经登录并具有适当的访问权限。如果验证失败,则需要将用户重定向到登录页面。

示例:

package mainimport ("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")// 检查是否存在会话IDif session.Values["authenticated"] != true {http.Redirect(w, r, "/login", 302)return}// 在此处处理受保护的页面
}func loginHandler(w http.ResponseWriter, r *http.Request) {// 在此处执行用户验证// 验证成功,创建sessionsession, _ := store.Get(r, "session-id")session.Values["authenticated"] = truesession.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"] = falsesession.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中删除。


golang session 应用程序中的状态管理

在Go语言中,使用session进行状态管理通常需要以下步骤:
1.创建一个session:在用户开始会话时,可以创建一个session来保存会话状态。这通常涉及到生成一个唯一的会话ID,并将该ID存储在一个cookie中。
2.存储状态:在处理每个请求时,可以将任何需要跟踪的状态信息存储在session中。这可以通过向session.Values中添加键值对来完成。
3.检索状态:在处理请求时,可以从session.Values中检索保存的状态信息。

一个示例:Go语言中使用Session进行状态管理

package mainimport ("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"]// 如果状态不存在,初始化为0if count == nil {count = 0}// 显示状态信息fmt.Fprintf(w, "Count: %d\n", count)// 将状态增加1count = count.(int) + 1// 存储新的状态session.Values["count"] = countsession.Save(r, w)
}func addHandler(w http.ResponseWriter, r *http.Request) {session, _ := store.Get(r, "session-id")// 检索保存的状态count := session.Values["count"]// 如果状态不存在,初始化为0if 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"] = countsession.Save(r, w)// 重定向到首页http.Redirect(w, r, "/", 302)
}

在上述示例中,我们使用session来存储一个计数器的状态。在处理每个请求时,我们从session.Values中检索计数器的值。如果该值不存在,我们将其初始化为0。在首页中,我们显示计数器的值,并将其增加1。在addHandler中,我们从请求参数中获取一个值,并将其添加到计数器的值中。最后,我们将新的计数器值保存到session.Values中,并重定向到首页。


golang实现在线人数统计

在Go语言中实现在线人数功能,可以用session来记录在线用户

package mainimport ("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 := 0store := 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信息。


golang 实现购物车应用

在go语言中可以使用session来实现购物车功能。以下是一个基本的购物车应用实例

package mainimport ("fmt""net/http""strconv""github.com/gorilla/mux""github.com/gorilla/sessions"
)var store = sessions.NewCookieStore([]byte("secret-key"))type Product struct {Name  stringPrice 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 <a href='/add-to-cart/%d'>Add to Cart</a><br>", 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"] = cartsession.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:<br>")for productID, quantity := range cart {product := getProductByID(productID)fmt.Fprintf(w, "%s - $%.2f x %d<br>", 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 {// 实际应用中,此处应根据商品信息生成唯一的IDreturn 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”]中获取购物车状态,并显示其中的商品和数量。


golang session用户个性化设置应用

package mainimport ("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, `<br/><br/><form action="/setcolor" method="POST"><label for="color">Select your color:</label><input type="text" name="color" id="color" /><input type="submit" value="Set Color" /></form><form action="/setfont" method="POST"><label for="font">Select your font:</label><input type="text" name="font" id="font" /><input type="submit" value="Set Font" /></form>`)
}func setColorHandler(w http.ResponseWriter, r *http.Request) {// 获取用户设置的颜色值color := r.FormValue("color")// 将颜色设置保存到session中session, _ := store.Get(r, "user-settings")session.Values["color"] = colorsession.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"] = fontsession.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中获取用户设置的颜色和字体,并将它们显示在网页上。我们还显示了一个表单,用于允许用户设置它们的颜色、字体。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/662582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git使用以及工作中开发流程

Git是当前最先进、最主流的分布式版本控制系统&#xff0c;免费、开源。 主要概念&#xff1a; 基本流程&#xff1a; 命令&#xff1a; git commit -a # 省略了add到暂存区的步骤&#xff0c;直接提交工作区的修改内容到版本库&#xff0c;不包括新增的文件。git fetc…

myql 项目数据库和表的设计

1.表的设计和创建 2.在navicate运行这些代码 create table user(id int not null auto_increment primary key,name varchar(50) not null unique,password varchar(50) not null,state enum(online,offline) default offline ); create table friend(userid int not null,…

day37WEB攻防-通用漏洞XSS跨站权限维持钓鱼捆绑浏览器漏洞

目录 XSS-后台植入 Cookie&表单劫持&#xff08;权限维持&#xff09; 案例演示 XSS-Flash 钓鱼配合 MSF 捆绑上线 1、生成后门 2、下载官方文件-保证安装正常 3、压缩捆绑文件-解压提取运行 4、MSF 配置监听状态 5、诱使受害者访问 URL-语言要适当 XSS-浏览器网马…

Unity之协同程序

一 Unity是否支持多线程 //首先要明确一点 //Unity是否支持多线程 //只是新开线程无法访问Unity相关对象的内容//注意 &#xff1a; Unity中的多线程 要记得关闭 t new Thread(Test); t.Start();//用处&#xff1a;在进行一些寻路算法运算以及网络通信相关内容时&#xff0c;…

Echars3D 饼图开发

关于vue echart3D 饼图开发 首先要先下载 "echarts-gl", 放在main.js npm install echarts-gl --save <template><div class"cointan"><!-- 3d环形图 --><div class"chart" id"cityGreenLand-charts"><…

03. 【Linux教程】安装虚拟机

前面小节介绍了 Linux 和 GUN 项目&#xff0c;本小节开始学习如何在 Windows 上安装虚拟机&#xff0c;虚拟机安装之后可以在虚拟机中安装 Linux 相关的操作系统&#xff0c;常见的虚拟机软件有 VirtualBox、VMware 等等&#xff0c;本教程使用 VMware 虚拟机软件来演示如何安…

java数据结构与算法刷题-----LeetCode198. 打家劫舍

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 很多人觉得动态规划很难&#xff0c;但它就是固定套路而已。其实动态规划只…

Flink CDC 3.0 详解

一、Flink CDC 概述 Flink CDC 是基于数据库日志 CDC&#xff08;Change Data Capture&#xff09;技术的实时数据集成框架&#xff0c;支持全增量一体化、无锁读取、并行读取、表结构变更自动同步、分布式架构等高级特性。配合Flink 优秀的管道能力和丰富的上下游生态&#x…

开启Android学习之旅-1

最近在学习《第一行代码 Android》&#xff0c;两天看书把所有代码都敲了一遍。由于之前没有接触过 Kotlin&#xff0c;导致了囫囵吞枣&#xff0c;跟着书会敲&#xff0c;离开就忘了。Android 大佬开发的各种框架、控件好像大部分都用了 Kotlin。看他们的源码&#xff0c;理解…

【每日一题】7.LeetCode——合并两个有序链表

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》|《数据结构与算法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢…

结束语_从困惑到启动

从22年9月份开始陆续碰到不少网络问题需要处理&#xff0c;基于问题驱动去学习相关的知识点。 23年上半年开始想进行总结输出&#xff0c;动手写的时候发现自己七窍通了六窍——一窍不通&#xff0c;又回过头来重新学习TCP/IP协议、计算机网络、wireshark抓包等相关知识。从酝酿…

【issue-YOLO】自定义数据集训练YOLO-v7 Segmentation

1. 拉取代码创建环境 执行nvidia-smi验证cuda环境是否可用&#xff1b;拉取官方代码&#xff1b; clone官方代码仓库 git clone https://github.com/WongKinYiu/yolov7&#xff1b;从main分支切换到u7分支 cd yolov7 && git checkout 44f30af0daccb1a3baecc5d80eae229…

C++——日期类

前言&#xff1a;哈喽小伙伴们&#xff0c;在上一篇文章中我们对C类与对象的前半段知识进行了简单的分享&#xff0c;其中比较重要的莫过于C类的六个默认成员函数。 所以这篇文章&#xff0c;我们通过实现一个完整的日期的操作&#xff0c;来对这些成员函数有一个更加深入的理…

你还不会使用git吗?

Git的基本概念包括工作区&#xff08;Workspace&#xff09;、暂存区&#xff08;Index/Stage&#xff09;和版本库&#xff08;Repository&#xff09;。 Git是一个分布式版本控制系统&#xff0c;它允许开发者在本地工作并保存他们的更改&#xff0c;然后再将这些更改推送到…

RabbitMQ-高级篇

服务异步通信-高级篇 消息队列在使用过程中&#xff0c;面临着很多实际问题需要思考&#xff1a; 1.消息可靠性 消息从发送&#xff0c;到消费者接收&#xff0c;会经理多个过程&#xff1a; 其中的每一步都可能导致消息丢失&#xff0c;常见的丢失原因包括&#xff1a; 发送…

Android 高德地图切换图层

一、默认样式 Android 地图 SDK 提供了几种预置的地图图层&#xff0c;包括卫星图、白昼地图&#xff08;即最常见的黄白色地图&#xff09;、夜景地图、导航地图、路况图层。 findViewById<TextView>(R.id.normal).setOnClickListener {updateSelectedStatus(TYPE_NORMA…

EasyExcel多线程导出并实现Zip压缩

前言&#xff1a;之前实现的需求由于导出时需要的时间过于长&#xff0c;需要优化采用多线程的方式进行导出 更改之后的代码&#xff1a; 首先创建excel的临时文件&#xff0c;并写入。然后创建线程池&#xff0c;调用zipArchiveOutputStream来写入图片和excel PostMapping(&qu…

Glide完全解读

一&#xff0c;概述 glide作为android流行的图片加载框架&#xff0c;笔者认为有必要对此完全解读。glide提供了三级缓存、生命周期Destroy后自动移除缓存、自动适配ImageView&#xff0c;以及提供了各种对图片修饰的操作&#xff0c;如剪裁等。本文通过最简单的使用&#xff…

Vue(二十):ElementUI 扩展实现表格组件的拖拽行

效果 源码 注意&#xff1a; 表格组件必须添加 row-key 属性&#xff0c;用来优化表格的渲染 <template><el-row :gutter"10"><el-col :span"12"><el-card class"card"><el-scrollbar><span>注意: 表格组件…

自动化测试再升级,大模型与软件测试相结合

近年来&#xff0c;软件行业一直在迅速发展&#xff0c;为了保证软件质量和提高效率&#xff0c;软件测试领域也在不断演进。如今&#xff0c;大模型技术的崛起为软件测试带来了前所未有的智能化浪潮。 软件测试一直是确保软件质量的关键环节&#xff0c;但传统的手动测试方法存…