package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" "strings" ) func main() { // 构造DSN字符串,格式 ☛ 账号:密码@tcp(主机地址:端口号)/数据库名?charset=字符编码 dataSourceName := "username:password@tcp(localhost:3306)/database?charset=utf8mb4" db, err := sql.Open("mysql", dataSourceName) if err != nil { panic(err.Error()) } // 关闭数据库 defer func(db *sql.DB) { _ = db.Close() }(db) // 检查连接数据库是否成功 err = db.Ping() if err != nil { panic(err.Error()) } //========== 查询单条记录(指定字段) ==========// // 构造SQL语句 var query strings.Builder query.WriteString("SELECT ") query.WriteString(" `id`, ") query.WriteString(" `title`, ") query.WriteString(" `click` ") query.WriteString("FROM ") query.WriteString(" `prefix_article` ") query.WriteString("WHERE ") query.WriteString(" `id` = ? ") id := 53 // 创建变量用于保存字段值 var fieldId int64 var fieldTitle string var fieldClick int64 // 执行SQL并把查询结果的字段值保存到对应的变量 row := db.QueryRow(query.String(), id) err = row.Scan(&fieldId, &fieldTitle, &fieldClick) if err != nil { panic(err.Error()) } fmt.Printf("第%v篇 %v 【点击:%v】\n", fieldId, fieldTitle, fieldClick) //========== 查询单条记录(所有字段) ==========// // 构造SQL语句 query.Reset() query.WriteString("SELECT ") query.WriteString(" `*` ") query.WriteString("FROM ") query.WriteString(" `prefix_article` ") query.WriteString("WHERE ") query.WriteString(" `id` = ? ") id = 53 // 执行SQL rows, err := db.Query(query.String(), id) if err != nil { panic(err.Error()) } // 关闭结果集 defer func(rows *sql.Rows) { _ = rows.Close() }(rows) // 获取所有字段名 columns, err := rows.Columns() if err != nil { panic(err.Error()) } values := make([][]byte, len(columns)) // 用于保存字段值 dest := make([]any, len(columns)) for i := range values { dest[i] = &values[i] } // 遍历结果集 for rows.Next() { err = rows.Scan(dest...) if err != nil { panic(err.Error()) } } record := map[string]string{} // 用于保存记录(单条) for i := range values { record[columns[i]] = string(values[i]) } fmt.Printf("第%v篇 %v 【点击:%v】\n", record["id"], record["title"], record["click"]) //========== 查询多条记录(所有字段) ==========// page := 2 // 页码 pageSize := 5 // 每页显示记录数 // 构造SQL语句 query.Reset() query.WriteString("SELECT ") query.WriteString(" `*` ") query.WriteString("FROM ") query.WriteString(" `prefix_article` ") query.WriteString("ORDER BY ") query.WriteString(" `id` DESC ") query.WriteString("LIMIT ?, ? ") // 执行SQL rows, err = db.Query(query.String(), (page-1)*pageSize, pageSize) if err != nil { panic(err.Error()) } // 关闭结果集 defer func(rows *sql.Rows) { _ = rows.Close() }(rows) // 获取所有字段名 columns, err = rows.Columns() if err != nil { panic(err.Error()) } values = make([][]byte, len(columns)) // 用于保存字段值 dest = make([]any, len(columns)) for i := range values { dest[i] = &values[i] } var records []map[string]string // 用于保存记录(多条) // 遍历结果集 for rows.Next() { err = rows.Scan(dest...) if err != nil { panic(err.Error()) } r := map[string]string{} // 单条记录的数据 for j := range values { r[columns[j]] = string(values[j]) } records = append(records, r) } // 遍历所有记录 for _, value := range records { fmt.Printf("第%v篇 %v 【点击:%v】\n", value["id"], value["title"], value["click"]) } //========== 插入记录 ==========// // 构造SQL语句 query.Reset() query.WriteString("INSERT INTO") query.WriteString(" `prefix_article` ") query.WriteString("SET") query.WriteString(" `title` = ?, ") query.WriteString(" `click` = ? ") title := "PHP是世界上最好の语言" click := 1024 // 执行SQL exec, err := db.Exec(query.String(), title, click) if err != nil { panic(err.Error()) } // 获取记录的自增主键ID(如果没有自增主键则为0) insertId, err := exec.LastInsertId() if err != nil { panic(err.Error()) } fmt.Printf("insertId = %+v \n", insertId) //========== 更新记录 ==========// // 构造SQL语句 query.Reset() query.WriteString("UPDATE ") query.WriteString(" `prefix_article` ") query.WriteString("SET") query.WriteString(" `click` = ? ") query.WriteString("WHERE ") query.WriteString(" `id` = ? ") click = 10086 id = 10086 // 执行SQL result, err := db.Exec(query.String(), click, id) if err != nil { panic(err.Error()) } // 获取更新记录数 affected, err := result.RowsAffected() if err != nil { panic(err.Error()) } fmt.Printf("共更新%+v条记录\n", affected) //========== 删除记录 ==========// // 构造SQL语句 query.Reset() query.WriteString("DELETE FROM") query.WriteString(" `prefix_article` ") query.WriteString("WHERE ") query.WriteString(" `id` = ? ") id = 10086 // 执行SQL exec, err = db.Exec(query.String(), id) if err != nil { panic(err.Error()) } rowsAffected, err := exec.RowsAffected() if err != nil { panic(err.Error()) } fmt.Printf("共删除%+v条记录\n", rowsAffected) } //========== 总结 ==========// // 1、sql.Open()只验证其参数是否正确,并不创建与数据库的连接,想检查与数据库是否连接成功可以使用db.Ping()。 // 2、DB可以安全地供多个协程并发使用,并维护自己的空闲连接池,故sql.Open()应该只调用一次,很少需要调用db.Close()关闭数据库。 // 3、如果查询结果集使用了“for rows.Next()”遍历,也可以不调用rows.Close()手动关闭结果集,因为遍历完后会自动关闭,并且自动 // 关闭后再调用rows.Close()手动关闭也不会报错,因为Close()方法是幂等的,不过为了安全起见和养成良好的编码习惯,最好还是手 // 动关闭结果集。
Copyright © 2024 码农人生. All Rights Reserved