Changes: - Renamed all 10 Golang files from English to Chinese names - Created 00-项目概述/项目概述.md with comprehensive project overview - Created 08-算法与数据结构/算法与数据结构学习指南.md with detailed learning guide - Created 12-面试技巧/面试准备进度.md with progress tracking - Added .obsidian configuration for better markdown editing - Updated Claude.MD with Chinese filename rule Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
226 lines
4.1 KiB
Markdown
226 lines
4.1 KiB
Markdown
# Golang 数据库操作
|
||
|
||
## 问题
|
||
|
||
1. Go 如何连接 MySQL 数据库?
|
||
2. database/sql 的使用方法是什么?
|
||
3. 如何使用 ORM(如 GORM)?
|
||
4. 如何处理数据库事务?
|
||
5. 如何处理 SQL 注入?
|
||
|
||
---
|
||
|
||
## 标准答案
|
||
|
||
### 1. 连接 MySQL
|
||
|
||
#### **使用 database/sql**
|
||
|
||
```go
|
||
import (
|
||
"database/sql"
|
||
_ "github.com/go-sql-driver/mysql"
|
||
)
|
||
|
||
func main() {
|
||
// 连接数据库
|
||
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?parseTime=true"
|
||
db, err := sql.Open("mysql", dsn)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
defer db.Close()
|
||
|
||
// 测试连接
|
||
err = db.Ping()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
fmt.Println("Connected!")
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. database/sql 使用
|
||
|
||
#### **查询**
|
||
|
||
```go
|
||
func queryUser(db *sql.DB, id int) (string, error) {
|
||
var name string
|
||
err := db.QueryRow("SELECT name FROM users WHERE id = ?", id).Scan(&name)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return name, nil
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### **查询多行**
|
||
|
||
```go
|
||
func queryUsers(db *sql.DB) ([]string, error) {
|
||
rows, err := db.Query("SELECT name FROM users WHERE age > ?", 18)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
defer rows.Close()
|
||
|
||
var names []string
|
||
for rows.Next() {
|
||
var name string
|
||
if err := rows.Scan(&name); err != nil {
|
||
return nil, err
|
||
}
|
||
names = append(names, name)
|
||
}
|
||
|
||
return names, nil
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 使用 GORM
|
||
|
||
#### **安装**
|
||
|
||
```bash
|
||
go get -u gorm.io/gorm
|
||
go get -u gorm.io/driver/mysql
|
||
```
|
||
|
||
---
|
||
|
||
#### **基本使用**
|
||
|
||
```go
|
||
import (
|
||
"gorm.io/driver/mysql"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
type User struct {
|
||
ID uint `gorm:"primaryKey"`
|
||
Name string `gorm:"column:name"`
|
||
Age int `gorm:"column:age"`
|
||
}
|
||
|
||
func main() {
|
||
// 连接数据库
|
||
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
|
||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
defer db.Close()
|
||
|
||
// 自动迁移
|
||
db.AutoMigrate(&User{})
|
||
|
||
// 创建
|
||
user := User{Name: "Alice", Age: 25}
|
||
db.Create(&user)
|
||
|
||
// 查询
|
||
var users []User
|
||
db.Where("age > ?", 18).Find(&users)
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4. 事务处理
|
||
|
||
#### **database/sql 事务**
|
||
|
||
```go
|
||
func transfer(db *sql.DB, from, to int, amount int) error {
|
||
tx, err := db.Begin()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
defer func() {
|
||
if err != nil {
|
||
tx.Rollback()
|
||
} else {
|
||
tx.Commit()
|
||
}
|
||
}()
|
||
|
||
// 1. 扣款
|
||
_, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, from)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 2. 存款
|
||
_, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, to)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### **GORM 事务**
|
||
|
||
```go
|
||
func transfer(db *gorm.DB, from, to int, amount int) error {
|
||
return db.Transaction(func(tx *gorm.DB) error {
|
||
// 扣款
|
||
if err := tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, from).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
// 存款
|
||
if err := tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, to).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
})
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5. SQL 注入防护
|
||
|
||
#### ✅ 使用参数化查询
|
||
|
||
```go
|
||
// ✅ 安全(参数化查询)
|
||
db.Query("SELECT * FROM users WHERE id = ?", id)
|
||
|
||
// ❌ 不安全(字符串拼接)
|
||
db.Query(fmt.Sprintf("SELECT * FROM users WHERE id = %d", id))
|
||
```
|
||
|
||
---
|
||
|
||
### 6. 阿里 P7 加分项
|
||
|
||
**深度理解**:
|
||
- 理解 database/sql 的连接池机制
|
||
- 理解 GORM 的底层实现(基于 database/sql)
|
||
- 理解数据库事务的隔离级别
|
||
|
||
**实战经验**:
|
||
- 有处理数据库连接池的经验
|
||
- 有优化数据库查询的经验(索引、批量操作)
|
||
- 有处理分布式事务的经验
|
||
|
||
**性能优化**:
|
||
- 理解如何优化数据库查询(预编译语句、批量操作)
|
||
- 理解如何优化连接池配置
|
||
- 理解如何处理慢查询
|