天天看點

goweb——尚矽谷矽谷書城項目

概況

項目有controller、dao、model、utils、views、以及sql等包。

goweb——尚矽谷矽谷書城項目

項目說明

作為教程中的練手項目,項目中使用到了包括函數、切片、接口、指針在内的go基礎知識,以及action、cookie等web内容。

基于MySQL項目将使用人群分為了兩塊,使用者和管理者。

在使用者端,項目實作了登入、注冊、使用購物車、結算等功能。

而管理者不僅可以使用上述功能,同時也能使用管理購物項功能。

功能相對簡單但是頁面簡潔使用絲滑。

goweb——尚矽谷矽谷書城項目

代碼

1.主函數

package main

import (
	"bookstore0612/controller"
	"net/http"
)

func main() {
	//設定處理靜态資源,如css和js檔案
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("/bookstore0612/views/static"))))
	//直接去html頁面
	http.Handle("/pages/", http.StripPrefix("/pages/", http.FileServer(http.Dir("/bookstore0612/views/pages"))))
	//去首頁
	http.HandleFunc("/main", controller.GetPageBooksByPrice)
	//去登入
	http.HandleFunc("/login", controller.Login)
	//去登出
	http.HandleFunc("/logout", controller.Logout)
	//去注冊
	http.HandleFunc("/regist", controller.Regist)
	//通過Ajax請求驗證使用者名是否可用
	http.HandleFunc("/checkUserName", controller.CheckUserName)
	//擷取所有圖書
	// http.HandleFunc("/getBooks", controller.GetBooks)
	//擷取帶分頁的圖書資訊
	http.HandleFunc("/getPageBooks", controller.GetPageBooks)
	http.HandleFunc("/getPageBooksByPrice", controller.GetPageBooksByPrice)
	//添加圖書
	// http.HandleFunc("/addBook", controller.AddBook)
	//删除圖書
	http.HandleFunc("/deleteBook", controller.DeleteBook)
	//去更新圖書的頁面
	http.HandleFunc("/toUpdateBookPage", controller.ToUpdateBookPage)
	//更新或添加圖書
	http.HandleFunc("/updateOraddBook", controller.UpdateOrAddBook)
	//添加圖書到購物車中
	http.HandleFunc("/addBook2Cart", controller.AddBook2Cart)
	//擷取購物車資訊
	http.HandleFunc("/getCartInfo", controller.GetCartInfo)
	//清空購物車
	http.HandleFunc("/deleteCart", controller.DeleteCart)
	//删除購物項
	http.HandleFunc("/deleteCartItem", controller.DeleteCartItem)
	//更新購物項
	http.HandleFunc("/updateCartItem", controller.UpdateCartItem)
	//去結賬
	http.HandleFunc("/checkout", controller.Checkout)
	//擷取所有訂單
	http.HandleFunc("/getOrders", controller.GetOrders)
	//擷取訂單詳情,即訂單所對應的所有的訂單項
	http.HandleFunc("/getOrderInfo", controller.GetOrderInfo)
	//擷取我的訂單
	http.HandleFunc("/getMyOrder", controller.GetMyOrders)
	//發貨
	http.HandleFunc("/sendOrder", controller.SendOrder)
	//确認收貨
	http.HandleFunc("/takeOrder", controller.TakeOrder)

	http.ListenAndServe(":8090", nil)
}

           

2. controller包(控制層)

我認為這個包應該是項目中最重要也是最核心的部分,了解了這個部分應該就能夠對項目有一個大概的認知

2.1 bookhandle(圖書管理)

圖書是擁有很多屬性的。管理起來也是很麻煩是以用到了四個函數。分别為GetPageBooksByPrice、GetPageBooks、DeleteBook、ToUpdateBookPage、UpdateOrAddBook。顧名思義,GetPageBooksByPrice作用是 擷取帶分頁和價格範圍的圖書、GetPageBooks 的作用擷取帶分頁的圖書、DeleteBook 的作用是删除圖書、ToUpdateBookPage 的作用是去更新或者添加圖書的頁面、UpdateOrAddBook 的作用是更新或添加圖書

package controller

import (
	"bookstore0612/dao"
	"bookstore0612/model"
	"html/template"
	"net/http"
	"strconv"
)


func GetPageBooksByPrice(w http.ResponseWriter, r *http.Request) {
	//擷取頁碼
	pageNo := r.FormValue("pageNo")
	//擷取價格範圍
	minPrice := r.FormValue("min")
	maxPrice := r.FormValue("max")
	if pageNo == "" {
		pageNo = "1"
	}
	var page *model.Page
	if minPrice == "" && maxPrice == "" {
		//調用bookdao中擷取帶分頁的圖書的函數
		page, _ = dao.GetPageBooks(pageNo)
	} else {
		//調用bookdao中擷取帶分頁和價格範圍的圖書的函數
		page, _ = dao.GetPageBooksByPrice(pageNo, minPrice, maxPrice)
		//将價格範圍設定到page中
		page.MinPrice = minPrice
		page.MaxPrice = maxPrice
	}
	//調用IsLogin函數判斷是否已經登入
	flag, session := dao.IsLogin(r)

	if flag {
		//已經登入,設定page中的IsLogin字段和Username的字段值
		page.IsLogin = true
		page.Username = session.UserName
	}

	//解析模闆檔案
	t := template.Must(template.ParseFiles("views/index.html"))
	//執行
	t.Execute(w, page)
}

func GetPageBooks(w http.ResponseWriter, r *http.Request) {
	//擷取頁碼
	pageNo := r.FormValue("pageNo")
	if pageNo == "" {
		pageNo = "1"
	}
	//調用bookdao中擷取帶分頁的圖書的函數
	page, _ := dao.GetPageBooks(pageNo)
	//解析模闆檔案
	t := template.Must(template.ParseFiles("views/pages/manager/book_manager.html"))
	//執行
	t.Execute(w, page)
}

func DeleteBook(w http.ResponseWriter, r *http.Request) {
	//擷取要删除的圖書的id
	bookID := r.FormValue("bookId")
	//調用bookdao中删除圖書的函數
	dao.DeleteBook(bookID)
	//調用GetBooks處理器函數再次查詢一次資料庫
	GetPageBooks(w, r)
}

func ToUpdateBookPage(w http.ResponseWriter, r *http.Request) {
	//擷取要更新的圖書的id
	bookID := r.FormValue("bookId")
	//調用bookdao中擷取圖書的函數
	book, _ := dao.GetBookByID(bookID)
	if book.ID > 0 {
		//在更新圖書
		//解析模闆
		t := template.Must(template.ParseFiles("views/pages/manager/book_edit.html"))
		//執行
		t.Execute(w, book)
	} else {
		//在添加圖書
		//解析模闆
		t := template.Must(template.ParseFiles("views/pages/manager/book_edit.html"))
		//執行
		t.Execute(w, "")
	}
}

func UpdateOrAddBook(w http.ResponseWriter, r *http.Request) {
	//擷取圖書資訊
	bookID := r.PostFormValue("bookId")
	title := r.PostFormValue("title")
	author := r.PostFormValue("author")
	price := r.PostFormValue("price")
	sales := r.PostFormValue("sales")
	stock := r.PostFormValue("stock")
	//将價格、銷量和庫存進行轉換
	fPrice, _ := strconv.ParseFloat(price, 64)
	iSales, _ := strconv.ParseInt(sales, 10, 0)
	iStock, _ := strconv.ParseInt(stock, 10, 0)
	ibookID, _ := strconv.ParseInt(bookID, 10, 0)
	//建立Book
	book := &model.Book{
		ID:      int(ibookID),
		Title:   title,
		Author:  author,
		Price:   fPrice,
		Sales:   int(iSales),
		Stock:   int(iStock),
		ImgPath: "/static/img/default.jpg",
	}
	if book.ID > 0 {
		//在更新圖書
		//調用bookdao中更新圖書的函數
		dao.UpdateBook(book)
	} else {
		//在添加圖書
		//調用bookdao中添加圖書的函數
		dao.AddBook(book)
	}
	//調用GetBooks處理器函數再次查詢一次資料庫
	GetPageBooks(w, r)
}

           

2.2cartthandler(購物車部分)

購物車部分實作的功能有:添加圖書、擷取購物車資訊、清空購物車、删除購物項、更新購物項。同樣使用到了四個函數。

AddBook2Cart添加圖書到購物車、GetCartInfo 根據使用者的id擷取購物車資訊、DeleteCart 清空購物車、DeleteCartItem 删除購物項、UpdateCartItem 更新購物項、

package controller

import (
	"bookstore0612/dao"
	"bookstore0612/model"
	"bookstore0612/utils"
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"strconv"
)

func AddBook2Cart(w http.ResponseWriter, r *http.Request) {
	//判斷是否登入
	flag, session := dao.IsLogin(r)
	if flag {
		//已經登入
		//擷取要添加的圖書的id
		bookID := r.FormValue("bookId")
		//根據圖書的id擷取圖書資訊
		book, _ := dao.GetBookByID(bookID)

		//擷取使用者的id
		userID := session.UserID
		//判斷資料庫中是否有目前使用者的購物車
		cart, _ := dao.GetCartByUserID(userID)
		if cart != nil {
			//目前使用者已經有購物車,此時需要判斷購物車中是否有目前這本圖書
			carItem, _ := dao.GetCartItemByBookIDAndCartID(bookID, cart.CartID)
			if carItem != nil {
				//購物車的購物項中已經有該圖書,隻需要将該圖書所對應的購物項中的數量加1即可
				//1.擷取購物車切片中的所有的購物項
				cts := cart.CartItems
				//2.周遊得到每一個購物項
				for _, v := range cts {
					fmt.Println("目前購物項中是否有Book:", v)
					fmt.Println("查詢到的Book是:", carItem.Book)
					//3.找到目前的購物項
					if v.Book.ID == carItem.Book.ID {
						//将購物項中的圖書的數量加1
						v.Count = v.Count + 1
						//更新資料庫中該購物項的圖書的數量
						dao.UpdateBookCount(v)
					}
				}
			} else {
				//購物車的購物項中還沒有該圖書,此時需要建立一個購物項并添加到資料庫中
				//建立購物車中的購物項
				cartItem := &model.CartItem{
					Book:   book,
					Count:  1,
					CartID: cart.CartID,
				}
				//将購物項添加到目前cart的切片中
				cart.CartItems = append(cart.CartItems, cartItem)
				//将新建立的購物項添加到資料庫中
				dao.AddCartItem(cartItem)
			}
			//不管之前購物車中是否有目前圖書對應的購物項,都需要更新購物車中的圖書的總數量和總金額
			dao.UpdateCart(cart)
		} else {
			//證明目前使用者還沒有購物車,需要建立一個購物車并添加到資料庫中
			//1.建立購物車
			//生成購物車的id
			cartID := utils.CreateUUID()
			cart := &model.Cart{
				CartID: cartID,
				UserID: userID,
			}
			//2.建立購物車中的購物項
			//聲明一個CartItem類型的切片
			var cartItems []*model.CartItem
			cartItem := &model.CartItem{
				Book:   book,
				Count:  1,
				CartID: cartID,
			}
			//将購物項添加到切片中
			cartItems = append(cartItems, cartItem)
			//3将切片設定到cart中
			cart.CartItems = cartItems
			//4.将購物車cart儲存到資料庫中
			dao.AddCart(cart)
		}
		w.Write([]byte("您剛剛将" + book.Title + "添加到了購物車!"))
	} else {
		//沒有登入
		w.Write([]byte("請先登入!"))
	}
}

func GetCartInfo(w http.ResponseWriter, r *http.Request) {
	_, session := dao.IsLogin(r)
	//擷取使用者的id
	userID := session.UserID
	//根據使用者的id從資料庫中擷取對應的購物車
	cart, _ := dao.GetCartByUserID(userID)
	if cart != nil {
		//将購物車設定到session中
		session.Cart = cart
		//解析模闆檔案
		t := template.Must(template.ParseFiles("views/pages/cart/cart.html"))
		//執行
		t.Execute(w, session)
	} else {
		//該使用者還沒有購物車
		//解析模闆檔案
		t := template.Must(template.ParseFiles("views/pages/cart/cart.html"))
		//執行
		t.Execute(w, session)
	}
}

func DeleteCart(w http.ResponseWriter, r *http.Request) {
	//擷取要删除的購物車的id
	cartID := r.FormValue("cartId")
	//清空購物車
	dao.DeleteCartByCartID(cartID)
	//調用GetCartInfo函數再次查詢購物車資訊
	GetCartInfo(w, r)
}

func DeleteCartItem(w http.ResponseWriter, r *http.Request) {
	//擷取要删除的購物項的id
	cartItemID := r.FormValue("cartItemId")
	//将購物項的id轉換為int64
	iCartItemID, _ := strconv.ParseInt(cartItemID, 10, 64)
	//擷取session
	_, session := dao.IsLogin(r)
	//擷取使用者的id
	userID := session.UserID
	//擷取該使用者的購物車
	cart, _ := dao.GetCartByUserID(userID)
	//擷取購物車中的所有的購物項
	cartItems := cart.CartItems
	//周遊得到每一個購物項
	for k, v := range cartItems {
		//尋找要删除的購物項
		if v.CartItemID == iCartItemID {
			//這個就是我們要删除的購物項
			//将目前購物項從切片中移出
			cartItems = append(cartItems[:k], cartItems[k+1:]...)
			//将删除購物項之後的切片再次賦給購物車中的切片
			cart.CartItems = cartItems
			//将目前購物項從資料庫中删除
			dao.DeleteCartItemByID(cartItemID)
		}
	}
	//更新購物車中的圖書的總數量和總金額
	dao.UpdateCart(cart)
	//調用擷取購物項資訊的函數再次查詢購物車資訊
	GetCartInfo(w, r)
}

func UpdateCartItem(w http.ResponseWriter, r *http.Request) {
	//擷取要更新的購物項的id
	cartItemID := r.FormValue("cartItemId")
	//将購物項的id轉換為int64
	iCartItemID, _ := strconv.ParseInt(cartItemID, 10, 64)
	//擷取使用者輸入的圖書的數量
	bookCount := r.FormValue("bookCount")
	iBookCount, _ := strconv.ParseInt(bookCount, 10, 64)
	//擷取session
	_, session := dao.IsLogin(r)
	//擷取使用者的id
	userID := session.UserID
	//擷取該使用者的購物車
	cart, _ := dao.GetCartByUserID(userID)
	//擷取購物車中的所有的購物項
	cartItems := cart.CartItems
	//周遊得到每一個購物項
	for _, v := range cartItems {
		//尋找要更新的購物項
		if v.CartItemID == iCartItemID {
			//這個就是我們要更新的購物項
			//将目前購物項中的圖書的數量設定為使用者輸入的值
			v.Count = iBookCount
			//更新資料庫中該購物項的圖書的數量和金額小計
			dao.UpdateBookCount(v)
		}
	}
	//更新購物車中的圖書的總數量和總金額
	dao.UpdateCart(cart)
	//調用擷取購物項資訊的函數再次查詢購物車資訊
	cart, _ = dao.GetCartByUserID(userID)
	// GetCartInfo(w, r)
	//擷取購物車中圖書的總數量
	totalCount := cart.TotalCount
	//擷取購物車中圖書的總金額
	totalAmount := cart.TotalAmount
	var amount float64
	//擷取購物車中更新的購物項中的金額小計
	cIs := cart.CartItems
	for _, v := range cIs {
		if iCartItemID == v.CartItemID {
			//這個就是我們尋找的購物項,此時擷取目前購物項中的金額小計
			amount = v.Amount
		}
	}
	//建立Data結構
	data := model.Data{
		Amount:      amount,
		TotalAmount: totalAmount,
		TotalCount:  totalCount,
	}
	//将data轉換為json字元串
	json, _ := json.Marshal(data)
	//響應到浏覽器
	w.Write(json)
}

           

2.3 orderhandler(處理訂單)

這一部分實作的功能有:結賬、擷取所有訂單、擷取訂單對應的訂單項、擷取個人訂單、收貨、發貨。

package controller

import (
	"bookstore0612/dao"
	"bookstore0612/model"
	"bookstore0612/utils"
	"html/template"
	"net/http"
	"time"
)

//Checkout //去結賬
func Checkout(w http.ResponseWriter, r *http.Request) {
	//擷取session
	_, session := dao.IsLogin(r)
	//擷取使用者的id
	userID := session.UserID
	//擷取購物車
	cart, _ := dao.GetCartByUserID(userID)
	//生成訂單号
	orderID := utils.CreateUUID()
	//建立生成訂單的時間
	timeStr := time.Now().Format("2021-07-02 15:04:05")
	//建立Order
	order := &model.Order{
		OrderID:     orderID,
		CreateTime:  timeStr,
		TotalCount:  cart.TotalCount,
		TotalAmount: cart.TotalAmount,
		State:       0,
		UserID:      int64(userID),
	}
	//将訂單儲存到資料庫中
	dao.AddOrder(order)
	//儲存訂單項
	//擷取購物車中的購物項
	cartItems := cart.CartItems
	//周遊得到每一個購物項
	for _, v := range cartItems {
		//建立OrderItem
		orderItem := &model.OrderItem{
			Count:   v.Count,
			Amount:  v.Amount,
			Title:   v.Book.Title,
			Author:  v.Book.Author,
			Price:   v.Book.Price,
			ImgPath: v.Book.ImgPath,
			OrderID: orderID,
		}
		//将購物項儲存到資料庫中
		dao.AddOrderItem(orderItem)
		//更新目前購物項中圖書的庫存和銷量
		book := v.Book
		book.Sales = book.Sales + int(v.Count)
		book.Stock = book.Stock - int(v.Count)
		//更新圖書的資訊
		dao.UpdateBook(book)
	}
	//清空購物車
	dao.DeleteCartByCartID(cart.CartID)
	//将訂單号設定到session中
	session.OrderID = orderID
	//解析模闆
	t := template.Must(template.ParseFiles("views/pages/cart/checkout.html"))
	//執行
	t.Execute(w, session)
}

//GetOrders 擷取所有訂單
func GetOrders(w http.ResponseWriter, r *http.Request) {
	//調用dao中擷取所有訂單的函數
	orders, _ := dao.GetOrders()
	//解析模闆
	t := template.Must(template.ParseFiles("views/pages/order/order_manager.html"))
	//執行
	t.Execute(w, orders)
}

//GetOrderInfo 擷取訂單對應的訂單項
func GetOrderInfo(w http.ResponseWriter, r *http.Request) {
	//擷取訂單号
	orderID := r.FormValue("orderId")
	//根據訂單号調用dao中擷取所有訂單項的函數
	orderItems, _ := dao.GetOrderItemsByOrderID(orderID)
	//解析模闆
	t := template.Must(template.ParseFiles("views/pages/order/order_info.html"))
	//執行
	t.Execute(w, orderItems)
}

//GetMyOrders 擷取我的訂單
func GetMyOrders(w http.ResponseWriter, r *http.Request) {
	//擷取session
	_, session := dao.IsLogin(r)
	//擷取使用者的id
	userID := session.UserID
	//調用dao中擷取使用者的所有訂單的函數
	orders, _ := dao.GetMyOrders(userID)
	//将訂單設定到session中
	session.Orders = orders
	//解析模闆
	t := template.Must(template.ParseFiles("views/pages/order/order.html"))
	//執行
	t.Execute(w, session)
}

//SendOrder 發貨
func SendOrder(w http.ResponseWriter, r *http.Request) {
	//擷取要發貨的訂單号
	orderID := r.FormValue("orderId")
	//調用dao中的更新訂單狀态的函數
	dao.UpdateOrderState(orderID, 1)
	//調用GetOrders函數再次查詢一下所有的訂單
	GetOrders(w, r)
}

//TakeOrder 收貨
func TakeOrder(w http.ResponseWriter, r *http.Request) {
	//擷取要收貨的訂單号
	orderID := r.FormValue("orderId")
	//調用dao中的更新訂單狀态的函數
	dao.UpdateOrderState(orderID, 2)
	//調用擷取我的訂單的函數再次查詢我的訂單
	GetMyOrders(w, r)
}

           

2.4userhandler(登入注冊)

package controller

import (
	"bookstore0612/dao"
	"bookstore0612/model"
	"bookstore0612/utils"
	"html/template"
	"net/http"
	"time"
)

//Checkout //去結賬
func Checkout(w http.ResponseWriter, r *http.Request) {
	//擷取session
	_, session := dao.IsLogin(r)
	//擷取使用者的id
	userID := session.UserID
	//擷取購物車
	cart, _ := dao.GetCartByUserID(userID)
	//生成訂單号
	orderID := utils.CreateUUID()
	//建立生成訂單的時間
	timeStr := time.Now().Format("2021-07-02 15:04:05")
	//建立Order
	order := &model.Order{
		OrderID:     orderID,
		CreateTime:  timeStr,
		TotalCount:  cart.TotalCount,
		TotalAmount: cart.TotalAmount,
		State:       0,
		UserID:      int64(userID),
	}
	//将訂單儲存到資料庫中
	dao.AddOrder(order)
	//儲存訂單項
	//擷取購物車中的購物項
	cartItems := cart.CartItems
	//周遊得到每一個購物項
	for _, v := range cartItems {
		//建立OrderItem
		orderItem := &model.OrderItem{
			Count:   v.Count,
			Amount:  v.Amount,
			Title:   v.Book.Title,
			Author:  v.Book.Author,
			Price:   v.Book.Price,
			ImgPath: v.Book.ImgPath,
			OrderID: orderID,
		}
		//将購物項儲存到資料庫中
		dao.AddOrderItem(orderItem)
		//更新目前購物項中圖書的庫存和銷量
		book := v.Book
		book.Sales = book.Sales + int(v.Count)
		book.Stock = book.Stock - int(v.Count)
		//更新圖書的資訊
		dao.UpdateBook(book)
	}
	//清空購物車
	dao.DeleteCartByCartID(cart.CartID)
	//将訂單号設定到session中
	session.OrderID = orderID
	//解析模闆
	t := template.Must(template.ParseFiles("views/pages/cart/checkout.html"))
	//執行
	t.Execute(w, session)
}

//GetOrders 擷取所有訂單
func GetOrders(w http.ResponseWriter, r *http.Request) {
	//調用dao中擷取所有訂單的函數
	orders, _ := dao.GetOrders()
	//解析模闆
	t := template.Must(template.ParseFiles("views/pages/order/order_manager.html"))
	//執行
	t.Execute(w, orders)
}

//GetOrderInfo 擷取訂單對應的訂單項
func GetOrderInfo(w http.ResponseWriter, r *http.Request) {
	//擷取訂單号
	orderID := r.FormValue("orderId")
	//根據訂單号調用dao中擷取所有訂單項的函數
	orderItems, _ := dao.GetOrderItemsByOrderID(orderID)
	//解析模闆
	t := template.Must(template.ParseFiles("views/pages/order/order_info.html"))
	//執行
	t.Execute(w, orderItems)
}

//GetMyOrders 擷取我的訂單
func GetMyOrders(w http.ResponseWriter, r *http.Request) {
	//擷取session
	_, session := dao.IsLogin(r)
	//擷取使用者的id
	userID := session.UserID
	//調用dao中擷取使用者的所有訂單的函數
	orders, _ := dao.GetMyOrders(userID)
	//将訂單設定到session中
	session.Orders = orders
	//解析模闆
	t := template.Must(template.ParseFiles("views/pages/order/order.html"))
	//執行
	t.Execute(w, session)
}

//SendOrder 發貨
func SendOrder(w http.ResponseWriter, r *http.Request) {
	//擷取要發貨的訂單号
	orderID := r.FormValue("orderId")
	//調用dao中的更新訂單狀态的函數
	dao.UpdateOrderState(orderID, 1)
	//調用GetOrders函數再次查詢一下所有的訂單
	GetOrders(w, r)
}

//TakeOrder 收貨
func TakeOrder(w http.ResponseWriter, r *http.Request) {
	//擷取要收貨的訂單号
	orderID := r.FormValue("orderId")
	//調用dao中的更新訂單狀态的函數
	dao.UpdateOrderState(orderID, 2)
	//調用擷取我的訂單的函數再次查詢我的訂單
	GetMyOrders(w, r)
}

           

因代碼量過大,僅展示主函數以及controller包的部分。見諒。

項目總結

本次項目的實踐對于初學者具有重要的意義。通過學習和完善該項目,鞏固了go基礎知識、學習到了web中的基礎知,同時對項目有了一個基礎的認知。

繼續閱讀