Go语言编程笔记16:存储数据

Go语言编程笔记16:存储数据

image-20211108153040805

图源:wallpapercave.com

几乎任何程序都绕不开读写数据,只不过具体的数据存储介质和方式有所不同。本篇文章将从多种数据存储方式进行探讨各种存储方式如何实现以及优劣。

内存

最简单也是最容易想到的方式大概就是用内存存储数据,事实上这也是大多数初学者不经意间最先学到的。

乍一听用内存存储数据显得很高级,其实所有程序运行时申请的变量都是在使用内存来存储数据。

不过作为Web应用,使用内存存储数据必须考虑并发,所以应当使用通道或者互斥锁来实现并发的数据读写。这里给出一个简陋的论坛应用。这个非常简陋的应用只实现了几个核心功能:

  • /login展现一个登陆页面,输入任意的非空用户名和密码可以登录。
  • /all_articles展示目前所有的帖子,包含帖子序号、内容、用户名。并且可以在最下方的文本框输入信息并添加一个新的帖子。可以通过上方的exit链接注销用户并退出。

下面给出完整程序:

main.go

package main

import (
	"errors"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"sync"
	"time"
)

type Article struct {
   
	Id      int
	Content string
	Author  string
}

var aMutex sync.RWMutex
var articles []*Article

const COOKIE_USER_NAME = "user_name"

func addArticle(content string, author string) {
   
	aMutex.Lock()
	defer aMutex.Unlock()
	aLen := len(articles)
	newArticle := Article{
   
		Id:      aLen,
		Content: content,
		Author:  author,
	}
	articles = append(articles, &newArticle)
}

func getArticles() []Article {
   
	aMutex.RLock()
	defer aMutex.RUnlock()
	var aCopy []Article
	for _, a := range articles {
   
		aCopy = append(aCopy, *a)
	}
	return aCopy
}

func getUserName(rw http.ResponseWriter, r *http.Request) (userName string, err error) {
   
	lc, err := r.Cookie(COOKIE_USER_NAME)
	if err != nil || lc.Value == "" {
   
		//去登录
		rw.Header().Set("Location", "/login")
		rw.WriteHeader(301)
		err = errors.New("need login")
		return
	}
	userName = lc.Value
	return
}

func doLogin(rw http.ResponseWriter, user string) {
   
	lc := http.Cookie{
   
		Name:  COOKIE_USER_NAME,
		Value: user,
	}
	rw.Header().Set("Set-Cookie", lc.String())
}

func unLogin(rw http.ResponseWriter) {
   
	lc := http.Cookie{
   
		Name:    COOKIE_USER_NAME,
		Value:   "",
		Expires: time.Unix(1, 0),
		MaxAge:  -1,
	}
	rw.Header().Set("Set-Cookie", lc.String())
}

func login(rw http.ResponseWriter, r *http.Request) {
   
	t := template.Must(template.ParseFiles("login.html"))
	t.Execute(rw, nil)
}

func loginCheck(rw http.ResponseWriter, r *http.Request) {
   
	un := r.PostFormValue("user_name")
	p := r.PostFormValue("password")
	if un == "" && p == "" {
   
		log.Fatal(errors.New("user name and password is empty"))
	}
	doLogin(rw, un)
	rw.Header().Set("Location", "/all_articles")
	rw.WriteHeader(301)
}

func allArticles(rw http.ResponseWriter, r *http.Request) {
   
	data := struct {
   
		UserName string
		Articles []Article
	}{
   }
	data.Articles = getArticles()
	un, err := getUserName(rw, r)
	if err != nil {
   
		fmt.Println(err)
		rw.Header().Set("Location", "/login")
		rw.WriteHeader(301)
		return
	}
	data.UserName = un
	t := template.Must(template.ParseFiles("articles.html"))
	t.Execute(rw, data)
}

func addArticleHandle(rw http.ResponseWriter, r *http.Request) {
   
	content := r.PostFormValue("content")
	author, err := getUserName(rw, r)
	if err != nil {
   
		fmt.Println(err)
		return
	}
	addArticle(content, author)
	rw.Header().Set
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值