Web基础Web工作方式客户端-服务器模型:Web应用基于客户端-服务器架构。客户端(如浏览器)通过HTTP协议向服务器发送请求,服务器响应这些请求。请求与响应:每个Web交互都包含一个从客户端到服务器的请求和从服务器到客户端的响应。使用Go搭建一个简单的Web服务packagema
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", helloHandler)
http.ListenAndServe(":8080", nil)
}
这段代码创建了一个监听8080端口的简单Web服务器,任何访问根路径/的请求都会被重定向到helloHandler函数处理。
基本概念
主要功能
初始化服务器
http.HandleFunc("/", handlerFunc)
http.ListenAndServe(":8080", nil)
处理请求
func handlerFunc(w http.ResponseWriter, r *http.Request) {
// 处理逻辑
}
读取请求参数
go
func handlerFunc(w http.ResponseWriter, r *http.Request) {
param := r.URL.Query().Get("name")
fmt.Fprintf(w, "Hello, %s!", param)
}
设置响应头
go
func handlerFunc(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"message": "Hello"})
}
使用中间件
go
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("Handling request: %s", r.URL.Path)
next.ServeHTTP(w, r)
})
}
package main
import (
"fmt"
"html/template"
"net/http"
)
type FormData struct {
Name string
Email string
}
func formHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
err := r.ParseForm()
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
name := r.FormValue("name")
email := r.FormValue("email")
fmt.Fprintf(w, "Name: %s\nEmail: %s", name, email)
} else {
tmpl := template.Must(template.ParseFiles("form.html"))
tmpl.Execute(w, FormData{})
}
}
func main() {
http.HandleFunc("/", formHandler)
http.ListenAndServe(":8080", nil)
}
HTML模板 (form.html)
<!DOCTYPE html>
<html>
<head>
<title>Form Example</title>
</head>
<body>
<h1>Submit Form</h1>
<form action="/" method="post">
Name: <input type="text" name="name"><br>
Email: <input type="email" name="email"><br>
<button type="submit">Submit</button>
</form>
</body>
</html>
package main
import (
"fmt"
"html/template"
"net/http"
"strings"
)
type FormData struct {
Name string
Email string
Error string
}
func formHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
err := r.ParseForm()
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
name := r.FormValue("name")
email := r.FormValue("email")
if strings.TrimSpace(name) == "" || strings.TrimSpace(email) == "" {
data := FormData{Name: name, Email: email, Error: "Please fill in all fields."}
tmpl := template.Must(template.ParseFiles("form.html"))
tmpl.Execute(w, data)
return
}
fmt.Fprintf(w, "Name: %s\nEmail: %s", name, email)
} else {
tmpl := template.Must(template.ParseFiles("form.html"))
tmpl.Execute(w, FormData{})
}
}
func main() {
http.HandleFunc("/", formHandler)
http.ListenAndServe(":8080", nil)
}
HTML模板 (form.html)
<!DOCTYPE html>
<html>
<head>
<title>Form Example</title>
</head>
<body>
<h1>Submit Form</h1>
{{ if .Error }}
<p style="color:red;">{{ .Error }}</p>
{{ end }}
<form action="/" method="post">
Name: <input type="text" name="name" value="{{ .Name }}"><br>
Email: <input type="email" name="email" value="{{ .Email }}"><br>
<button type="submit">Submit</button>
</form>
</body>
</html>
package main
import (
"fmt"
"html/template"
"net/http"
"strings"
)
type FormData struct {
Name string
Email string
Error string
}
func formHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
err := r.ParseForm()
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
name := r.FormValue("name")
email := r.FormValue("email")
if strings.TrimSpace(name) == "" || strings.TrimSpace(email) == "" {
data := FormData{Name: name, Email: email, Error: "Please fill in all fields."}
tmpl := template.Must(template.ParseFiles("form.html"))
tmpl.Execute(w, data)
return
}
// Escape user input to prevent XSS
name = html.EscapeString(name)
email = html.EscapeString(email)
fmt.Fprintf(w, "Name: %s\nEmail: %s", name, email)
} else {
tmpl := template.Must(template.ParseFiles("form.html"))
tmpl.Execute(w, FormData{})
}
}
func main() {
http.HandleFunc("/", formHandler)
http.ListenAndServe(":8080", nil)
}
package main
import (
"fmt"
"html/template"
"net/http"
"strings"
)
type FormData struct {
Name string
Email string
Error string
Token string
}
func formHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
err := r.ParseForm()
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
token := r.FormValue("token")
if token != r.FormValue("csrf_token") {
http.Error(w, "Invalid CSRF token", http.StatusBadRequest)
return
}
name := r.FormValue("name")
email := r.FormValue("email")
if strings.TrimSpace(name) == "" || strings.TrimSpace(email) == "" {
data := FormData{Name: name, Email: email, Token: token, Error: "Please fill in all fields."}
tmpl := template.Must(template.ParseFiles("form.html"))
tmpl.Execute(w, data)
return
}
// Escape user input to prevent XSS
name = html.EscapeString(name)
email = html.EscapeString(email)
fmt.Fprintf(w, "Name: %s\nEmail: %s", name, email)
} else {
token := generateToken()
data := FormData{Token: token}
tmpl := template.Must(template.ParseFiles("form.html"))
tmpl.Execute(w, data)
}
}
func generateToken() string {
// Generate a random token here
return "random-token"
}
func main() {
http.HandleFunc("/", formHandler)
http.ListenAndServe(":8080", nil)
}
HTML模板 (form.html)
<!DOCTYPE html>
<html>
<head>
<title>Form Example</title>
</head>
<body>
<h1>Submit Form</h1>
{{ if .Error }}
<p style="color:red;">{{ .Error }}</p>
{{ end }}
<form action="/" method="post">
<input type="hidden" name="csrf_token" value="{{ .Token }}">
Name: <input type="text" name="name" value="{{ .Name }}"><br>
Email: <input type="email" name="email" value="{{ .Email }}"><br>
<button type="submit">Submit</button>
</form>
</body>
</html>
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
)
func uploadHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
r.ParseMultipartForm(10 << 20) // 10 MB limit
file, handler, err := r.FormFile("upload")
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer file.Close()
tempFile, err := ioutil.TempFile("uploads", "upload-*.png")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer tempFile.Close()
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tempFile.Write(fileBytes)
fmt.Fprintf(w, "Successfully uploaded %s\n", handler.Filename)
} else {
tmpl := template.Must(template.ParseFiles("upload.html"))
tmpl.Execute(w, nil)
}
}
func main() {
http.HandleFunc("/", uploadHandler)
http.ListenAndServe(":8080", nil)
}
HTML模板 (upload.html)
<!DOCTYPE html>
<html>
<head>
<title>Upload File</title>
</head>
<body>
<h1>Upload File</h1>
<form action="/" method="post" enctype="multipart/form-data">
Select file to upload:
<input type="file" name="upload">
<button type="submit">Upload</button>
</form>
</body>
</html>
基础概念
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}
rows, err := db.Query("SELECT id, name FROM users")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int
var name string
err := rows.Scan(&id, &name)
if err != nil {
log.Fatal(err)
}
fmt.Println(id, name)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}
// 创建表
_, err = db.Exec("CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255))")
if err != nil {
log.Fatal(err)
}
// 插入数据
_, err = db.Exec("INSERT INTO users (name) VALUES (?)", "Alice")
if err != nil {
log.Fatal(err)
}
// 查询数据
rows, err := db.Query("SELECT id, name FROM users")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int
var name string
err := rows.Scan(&id, &name)
if err != nil {
log.Fatal(err)
}
fmt.Println(id, name)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, err := sql.Open("sqlite3", "./test.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}
// 创建表
_, err = db.Exec("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)")
if err != nil {
log.Fatal(err)
}
// 插入数据
_, err = db.Exec("INSERT INTO users (name) VALUES (?)", "Alice")
if err != nil {
log.Fatal(err)
}
// 查询数据
rows, err := db.Query("SELECT id, name FROM users")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int
var name string
err := rows.Scan(&id, &name)
if err != nil {
log.Fatal(err)
}
fmt.Println(id, name)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
)
func main() {
db, err := sql.Open("postgres", "user=postgres dbname=mydb sslmode=disable password=secret")
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatal(err)
}
// 创建表
_, err = db.Exec("CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT)")
if err != nil {
log.Fatal(err)
}
// 插入数据
_, err = db.Exec("INSERT INTO users (name) VALUES ($1)", "Alice")
if err != nil {
log.Fatal(err)
}
// 查询数据
rows, err := db.Query("SELECT id, name FROM users")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int
var name string
err := rows.Scan(&id, &name)
if err != nil {
log.Fatal(err)
}
fmt.Println(id, name)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
package main
import (
"fmt"
"log"
"os"
"github.com/astaxie/beego/orm"
)
type User struct {
Id int
Name string
}
func init() {
orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
orm.RegisterModel(new(User))
}
func main() {
orm.Debug = true
o := orm.NewOrm()
o.Using("default") // 默认使用 default
// 创建表
o.CreateTable(&User{})
// 插入数据
user := User{Name: "Alice"}
id, err := o.Insert(&user)
if err != nil {
log.Fatal(err)
}
fmt.Println("Inserted ID:", id)
// 查询数据
var users []User
_, err = o.QueryTable("users").All(&users)
if err != nil {
log.Fatal(err)
}
for _, u := range users {
fmt.Println(u.Id, u.Name)
}
// 更新数据
user.Name = "Bob"
_, err = o.Update(&user)
if err != nil {
log.Fatal(err)
}
// 删除数据
_, err = o.Delete(&user)
if err != nil {
log.Fatal(err)
}
}
使用MongoDB
package main
import (
"context"
"fmt"
"log"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
client, err := mongo.Connect(context.TODO(), clientOptions)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(context.TODO())
collection := client.Database("test").Collection("users")
// 插入数据
user := bson.M{"name": "Alice"}
_, err = collection.InsertOne(context.TODO(), user)
if err != nil {
log.Fatal(err)
}
// 查询数据
var result bson.M
err = collection.FindOne(context.TODO(), bson.M{"name": "Alice"}).Decode(&result)
if err != nil {
log.Fatal(err)
}
fmt.Println(result)
// 更新数据
filter := bson.M{"name": "Alice"}
update := bson.M{"$set": bson.M{"name": "Bob"}}
_, err = collection.UpdateOne(context.TODO(), filter, update)
if err != nil {
log.Fatal(err)
}
// 删除数据
_, err = collection.DeleteOne(context.TODO(), bson.M{"name": "Bob"})
if err != nil {
log.Fatal(err)
}
}
Session:
Cookie:
在Go中,可以使用多种方法来管理和使用session。一种常见的方式是使用第三方库,如gorilla/sessions。
使用 gorilla/sessions 安装库:
go get github.com/gorilla/sessions
配置和创建 Session Store:
import (
"github.com/gorilla/sessions"
)
store := sessions.NewCookieStore([]byte("unique-secret-key"))
设置 Session:
session, _ := store.Get(r, "session-name")
session.Values["username"] = "John Doe"
err := session.Save(r, w)
if err != nil {
// 处理错误
}
获取 Session:
session, _ := store.Get(r, "session-name")
username, ok := session.Values["username"].(string)
if !ok {
// 用户名不存在或者类型转换失败
} else {
fmt.Println("Username is", username)
}
Session数据可以存储在不同的地方,包括但不限于:
Session劫持是指攻击者获取合法用户的会话标识符(通常是session ID),从而冒充该用户。为了防止这种情况发生,可以采取以下措施:
使用HTTPS:确保所有通信都是加密的,防止中间人攻击。
设置Cookie属性:
检测并限制IP地址或浏览器指纹的变化:如果用户从不同的位置或设备登录,要求重新验证身份。
基础概念
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
// 读取文件
file, err := os.Open("input.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
fm... 如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!