
2024年在線市場平臺的11大最佳支付解決方案
sql.Open
方法開始連接數據庫,第一個參數為所要連接的數據庫類型。第二個參數為dsn,可以理解為連接數據庫的參數信息。
這里在連接以后,又對連接進行了三個設置。
conn.SetConnMaxLifetime
為設置連接的空閑時間,為什么要設置這個參數以及該設置多少是有講究的。
有的MySQL服務器為了性能考慮,會設置主動斷開空閑連接的,默認8個小時,但是一般的dba不會設置那么長,很有可能會設置10秒或者更短,所以這個參數要設置的更短,這個參數可以登錄MySQL 服務器執行show global variables like '%timeout%';
來查看,有個wait_timeout
值,這里的值要設置比這個值更短。
conn.SetMaxOpenConns(10)
和conn.SetMaxOpenConns(10)
這兩個方法會初始化一個連接池,保證池子里會有足夠的連接,這個值要設置多少需要根據應用的并發情況。
但是SetMaxIdleConns
的值不要小于SetMaxOpenConns
設置的值,否則會導致頻繁的創建連接。
官方的解釋為
db.SetMaxIdleConns() is recommended to be set same to db.SetMaxOpenConns(). When it is smaller than SetMaxOpenConns(), connections can be opened and closed much more frequently than you expect
這里還有個需要注意的是,在import 時,有個_ "github.com/go-sql-driver/mysql"
這行代碼不能缺,該代碼會執行一下init方法,初始化一些變量,如果沒有這行的話,會由于一些變量未被初始化而panic.
一般情況下,我們會將數據庫連接對象放到一個全局的變量中,然后將不同的數據庫操作封裝到dao中。
在項目目錄下再創建一個global目錄,再創建一個global.go文件, 在該文件中定義一些需要全局使用的變量.
package global
import "database/sql"
var (
Mysql *sql.DB
)
之后在main.go中進行mysql變量的初始化
package main
import (
"github.com/gin-gonic/gin"
"yyxtest/db"
"yyxtest/global"
"yyxtest/handlers"
)
func main() {
r := gin.Default()
global.Mysql = db.InitDB()
userv1_h := handlers.UserV1{}
userv1 := r.Group("/user/v1")
{
userv1.GET("/check", userv1_h.CheckUsers)
}
r.Run(":8080")
}
global.Mysql = db.InitDB()
這行代碼為初始化全局的Mysql 對象, 之后我們創建一個dao文件夾,再創建一個userdao.go文件,這里封裝數據庫的查詢. 先寫一個查詢所有記錄的函數。
事先準備一個表,并插入幾條數據
id | name | age |
1 | 楊彥星 | 18 |
2 | 飯團兒 | 1 |
3 | aaa | 100 |
4 | bbb | 22 |
5 | ccc | 19 |
6 | 35 | |
7 | 46 |
在userdao.go中寫入以下代碼,
package dao
import "yyxtest/global"
type user struct {
ID int json:"id"
Name string json:"name"
Age int json:"age"
}
func GetAllUsers() []user {
rows, err :=global.Mysql.Query("select * from user_infos")
if err != nil{
return nil
}
var persons = make([]user, 0)
for rows.Next() {
var a user
err := rows.Scan(&a.ID, &a.Name, &a.Age)
if err != nil {
return nil
}
persons = append(persons, a)
}
return persons
}
GetAllUsers
函數執行select * from user_infos
, 并且將該查詢結果返回[]user 的結構體, 接下來再編寫路由處理類, userv1_h.CheckUsers
在handler 文件夾中再創建一個userv1.go
package handlers
import (
"github.com/gin-gonic/gin"
"yyxtest/dao"
)
type UserV1 struct {}
func (UserV1) CheckUsers(c *gin.Context) {
users := dao.GetAllUsers()
if users == nil{
c.JSON(200, gin.H{"error": 1, "msg": "查詢失敗"})
}
c.JSON(200, gin.H{"error":0, "msg":"查詢成功", "users": users})
}
運行服務,如果沒有什么意外的話將可以正常的請求到數據
如果在進行數據庫的查詢時,沒有對用戶的輸入進校驗,而是完全的進行字符串拼接,將會導致SQL注入的問題發生,如以下的代碼
func GetUser(name string) (user, error) {
sqlstr := fmt.Sprintf("select * from user_infos where name
='%s'", name)
row := global.Mysql.QueryRow(sqlstr)
var u user
err := row.Scan(&u.ID, &u.Name, &u.Age)
if err != nil {
return user{}, err
}
return u, nil
}
sqlstr 直接進行字符串拼接將會導致注入問題。
正確的做法應該是使用點位符
插入數據也比較簡單,使用Exec函數 ,在userdao.go中寫入以下代碼
func InsertUser(name string, age int) error {
exec, err := global.Mysql.Exec("INSERT into user_infos(name, age) values (?,?)", name, age)
if err != nil {
return err
}
_, err = exec.LastInsertId()
if err != nil {
return err
}
return nil
}
在處理類中寫入以下代碼
func (UserV1) AddUser(c *gin.Context) {
name := c.Query("name")
age := c.Query("age")
age_i, err:=strconv.Atoi(age)
if err!=nil{
c.JSON(200, gin.H{"error": 1, "msg": "age 參數不正確"})
}else{
err = dao.InsertUser(name, age_i)
if err!= nil{
c.JSON(200, gin.H{"error": 2, "msg": err.Error()})
}else{
c.JSON(200, gin.H{"error": 1, "msg": "插入成功"})
}
}
}
MySQL的初步使用還是比較簡單的,只是在初始化的時候定義好相應的對象,但是MySQL是個博大精深的數據庫,入門很簡單,但是想要深入還是需要很多的內功修煉的,之后再深入一些事務相關的查詢。
文章轉自微信公眾號@序語程言