Golang中单引号导致程序崩溃的问题探讨

Golang中单引号导致程序崩溃的问题探讨 我有一个插入例程,它不接受插入文本中的单引号:

single'quote

查询语句:

INSERT INTO posts (post_subject,post_desc,post_type,post_status) VALUES ('single'quote','test',0,0) RETURNING post_id

Go 代码:

func Insert(query string) int {
	id := 0
	err := db.QueryRow(query).Scan(&id)
	if err != nil {
		log.Fatal(err)
	}
	return id
}

这会导致 Go 崩溃,我收到如下错误信息:

pq: syntax error at or near "quote"

我的问题是,除了对每个字段都使用“replaceall”之外,还有其他方法吗?有时你确实希望在文本中使用单引号。是否有“允许单引号”的全局设置?我知道可以使用反引号(`),但难道没有其他方法吗?


更多关于Golang中单引号导致程序崩溃的问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

你是如何构建 INSERT 字符串的?single'quote 是你用来构建 SQL 的某个字符串的值吗?

更多关于Golang中单引号导致程序崩溃的问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个字符串,没错。但你如何构建它呢?就目前而言,这不是有效的 SQL。

请查看我上面更新的答案。

lutzhorn:

DB.Exec

我需要一个返回值吗?使用 db.Exec 可以实现吗?

DB.QueryRow 支持占位符:

row := db.QueryRow("INSERT INTO foo (col) VALUES ($1)", "single'quote")

lutzhorn:

你是如何构建 INSERT 字符串的?

INSERT INTO posts (post_subject,post_desc,post_type,post_status) VALUES ('single'quote','test',0,0) RETURNING post_id

lutzhorn:

但是,你如何构建它呢?

你为我指明了正确的方向。现在这个方法可以工作了。谢谢你!

query := "INSERT INTO posts (post_subject,post_desc,post_type,post_status) 
VALUES ($1, $2, 0, 0)
RETURNING post_id"

subject := r.FormValue("subject")
desc := r.FormValue("desc")
id := Insert(query, subject, desc)

查询函数:

func Insert(query string, subject string, desc string) int {
id := 0
	err := db.QueryRow(query, subject, desc).Scan(&id)
	if err != nil {
		log.Fatal(err)
	}
	return id
}

在Go中处理SQL查询时,单引号导致语法错误是因为没有正确进行参数化查询。直接拼接SQL字符串会导致SQL注入漏洞和这类语法问题。正确的方法是使用参数化查询。

以下是修正后的代码示例:

func InsertPost(subject, desc string, postType, status int) (int, error) {
    var id int
    query := `INSERT INTO posts (post_subject, post_desc, post_type, post_status) 
              VALUES ($1, $2, $3, $4) RETURNING post_id`
    
    err := db.QueryRow(query, subject, desc, postType, status).Scan(&id)
    if err != nil {
        return 0, err
    }
    return id, nil
}

// 使用示例
func main() {
    // 包含单引号的文本
    subject := "single'quote"
    desc := "test"
    
    id, err := InsertPost(subject, desc, 0, 0)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("插入成功,ID: %d\n", id)
}

对于更复杂的场景,可以使用命名参数(如果数据库驱动支持):

import (
    "database/sql"
    _ "github.com/lib/pq"
    "github.com/jmoiron/sqlx"
)

func InsertPostNamed(subject, desc string, postType, status int) (int, error) {
    var id int
    query := `INSERT INTO posts (post_subject, post_desc, post_type, post_status) 
              VALUES (:subject, :desc, :type, :status) RETURNING post_id`
    
    // 使用sqlx进行命名参数查询
    dbx := sqlx.NewDb(db, "postgres")
    rows, err := dbx.NamedQuery(query, map[string]interface{}{
        "subject": subject,
        "desc":    desc,
        "type":    postType,
        "status":  status,
    })
    if err != nil {
        return 0, err
    }
    defer rows.Close()
    
    if rows.Next() {
        err = rows.Scan(&id)
    }
    return id, err
}

对于批量插入,可以使用预处理语句:

func BatchInsertPosts(posts []Post) error {
    tx, err := db.Begin()
    if err != nil {
        return err
    }
    defer tx.Rollback()
    
    stmt, err := tx.Prepare(`INSERT INTO posts (post_subject, post_desc) VALUES ($1, $2)`)
    if err != nil {
        return err
    }
    defer stmt.Close()
    
    for _, post := range posts {
        _, err = stmt.Exec(post.Subject, post.Desc)
        if err != nil {
            return err
        }
    }
    
    return tx.Commit()
}

参数化查询会自动处理特殊字符的转义,包括单引号,同时防止SQL注入攻击。这是处理SQL查询中特殊字符的标准做法。

回到顶部