package main
import (
"database/sql"
"log"
// Import the SQLite driver anonymously to initialize it
// without directly referencing
_ "github.com/mattn/go-sqlite3"
)
// Declare a global variable to hold the database connection pool
var db *sql.DB
// initDB initializes the database connection and creates
// the 'notes' table if it doesn't exist
func initDB() {
var err error
// Open a connection to the SQLite database file named "notes.db"
db, err = sql.Open("sqlite3", "./notes.db")
if err != nil {
// Log any error that occurs and terminate the program
log.Fatal(err)
}
// SQL statement to create the notes table if it doesn't exist
createTable := `
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
content TEXT
);`
// Execute the SQL statement to create the table
_, err = db.Exec(createTable)
if err != nil {
// Log any error that occurs while executing the SQL statement
// and terminate the program
log.Fatal(err)
}
}
func main() {
// Initialize the database
initDB()
// Ensure the database connection is closed when the main function exits
defer db.Close()
// Set up HTTP handlers for different routes
http.HandleFunc("/", indexHandler) // Route for the homepage
http.HandleFunc("/add", addHandler) // Route for adding a new note
http.HandleFunc("/delete", deleteHandler) // Route for deleting a note
// Log the server start and listen on port 8080
log.Println("Server started at :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
// Retrieve all notes from the database
notes, err := GetNotes()
if err != nil {
// Send an internal server error response if something goes wrong
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Parse the HTML template file
tmpl, err := template.ParseFiles("index.html")
if err != nil {
// Send an internal server error response if the template cannot be parsed
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Execute the template with the notes data
tmpl.Execute(w, notes)
}
函数:add 处理器
add 处理器确保笔记将被添加到数据库中。 处理器包括以下功能:
检查请求方法:确保仅处理 POST 请求。
检索表单值:从表单中获取标题和内容值。
创建笔记:调用 CreateNote 将新笔记添加到数据库。
重定向:在添加笔记后将用户重定向回主页。
func addHandler(w http.ResponseWriter, r *http.Request) {
// Only handle POST requests
if r.Method == "POST" {
// Get the title and content from the form values
title := r.FormValue("title")
content := r.FormValue("content")
// Create a new note with the provided title and content
CreateNote(title, content)
}
// Redirect the user back to the homepage after adding the note
http.Redirect(w, r, "/", http.StatusSeeOther)
}
函数:delete 处理器
delete 处理器从数据库中删除笔记。 此处理器执行以下操作:
转换 ID:将表单值 id 转换为整数。 如果转换失败,它会发送一个错误请求响应。
删除笔记:调用 DeleteNote 删除数据库中具有指定 ID 的笔记。
重定向:在删除笔记后将用户重定向回主页。
func deleteHandler(w http.ResponseWriter, r *http.Request) {
// Convert the ID from the form value to an integer
id, err := strconv.Atoi(r.FormValue("id"))
if err != nil {
// Send a bad request response if the ID is not valid
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
// Delete the note with the given ID
DeleteNote(id)
// Redirect the user back to the homepage after deleting the note
http.Redirect(w, r, "/", http.StatusSeeOther)
}
package main
import (
"encoding/json"
"fmt"
"html/template"
"log"
"net/http"
"strconv"
)
// main function is the entry point of the program
func main() {
// Initialize the database
initDB()
// Ensure the database connection is closed when the main function exits
defer db.Close()
// Set up HTTP handlers for different routes
http.HandleFunc("/", indexHandler) // Route for the homepage
http.HandleFunc("/add", addHandler) // Route for adding a new note
http.HandleFunc("/delete", deleteHandler) // Route for deleting a note
// Log the server start and listen on port 8080
log.Println("Server started at :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
// indexHandler handles the requests to the homepage
func indexHandler(w http.ResponseWriter, r *http.Request) {
// Retrieve all notes from the database
notes, err := GetNotes()
if err != nil {
// Send an internal server error response if something goes
// wrong
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Parse the HTML template file
tmpl, err := template.ParseFiles("index.html")
if err != nil {
// Send an internal server error response if the template
// cannot be parsed
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Execute the template with the notes data
tmpl.Execute(w, notes)
}
// addHandler handles the requests to add a new note
func addHandler(w http.ResponseWriter, r *http.Request) {
// Only handle POST requests
if r.Method == "POST" {
// Get the title and content from the form values
title := r.FormValue("title")
content := r.FormValue("content")
// Create a new note with the provided title and content
CreateNote(title, content)
}
// Redirect the user back to the homepage after adding the note
http.Redirect(w, r, "/", http.StatusSeeOther)
}
// deleteHandler handles the requests to delete a note
func deleteHandler(w http.ResponseWriter, r *http.Request) {
// Convert the ID from the form value to an integer
id, err := strconv.Atoi(r.FormValue("id"))
if err != nil {
// Send a bad request response if the ID is not valid
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
// Delete the note with the given ID
DeleteNote(id)
// Redirect the user back to the homepage after deleting the note
http.Redirect(w, r, "/", http.StatusSeeOther)
}
步骤 6:创建 HTML 表单
现在让我们创建一个名为 index.html 的新文件,其中包含一个用于添加和删除笔记的表单。 此文件将使用 html/template 包。 Go 中的 html/template 包提供了解析和执行模板的功能。 像 {{range .}} 和 {{.Title}} 这样的占位符是 Go 模板语法的一部分,允许将动态内容插入到 HTML 中。
// Parse the HTML template file
tmpl, err := template.ParseFiles("index.html")
if err != nil {
// Send an internal server error response if the template cannot be parsed
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Execute the template with the notes data
tmpl.Execute(w, notes)