🐳 小技术 | Go 处理 MySQL Duplicate 错误的正确姿势

2,597 阅读1分钟

日常 Go 开发过程中经常会操作数据库,使用 INSERT 操作时可能会遇到主键或者唯一索引发生冲突的情况,日志输出的内容如下所示。

Error 1062: Duplicate entry '%s' for key %d

正确处理方式

断言 Error 接口为 mysql.MySQLError 类型,随后判断 Number 字段值为 1062 即可进行特殊处理。

import (
  "database/sql"
  "os""github.com/go-sql-driver/mysql"
  _ "github.com/go-sql-driver/mysql"
)
​
func main() {
  db, _ := sql.Open("mysql", os.Getenv("DSN"))
  
  _, err := db.Exec("INSERT INTO test_table(id) VALUES (1)")
  if err != nil {
    
    // make sure err is a mysql.MySQLError.
    if errMySQL, ok := err.(*mysql.MySQLError); ok {
      switch errMySQL.Number {
      case 1062:
        // TODO handle Error 1062: Duplicate entry '%s' for key %d
      }
    }
    
  }
}

原理

日志输出的内容是 Go 基本库 Error 接口的 Error 方法结果,如果我们使用的是 go-sql-driver 作为 Driver,那么 Error 接口的实现是 go-sql-driver 内的 MySQLError 结构体。

代码位置在 go-sql-driver/mysql/blob/master/errors.go#L58,源码如下所示。

// MySQLError is an error type which represents a single MySQL error
type MySQLError struct {
  Number  uint16
  Message string
}
​
func (me *MySQLError) Error() string {
  return fmt.Sprintf("Error %d: %s", me.Number, me.Message)
}

根据上述原理进行类推,我们可以根据全部 MySQL 错误代码进行处理。

参考资料

关于 MySQL 错误,您可以查阅 MySQL 官方文档 - Chapter 2 Server Error Message Reference