Skip to content

Instantly share code, notes, and snippets.

@tanapoln
Created September 14, 2020 11:41
Show Gist options
  • Save tanapoln/75ba9d86e9752037e14fbbd88906bcf1 to your computer and use it in GitHub Desktop.
Save tanapoln/75ba9d86e9752037e14fbbd88906bcf1 to your computer and use it in GitHub Desktop.
How to handle optimistic lock in go
package main
import (
"database/sql"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
func init() {
var err error
db, err = sql.Open("mysql", "root:root@tcp(localhost:3306)/demo")
if err != nil {
panic(err)
}
if err := db.Ping(); err != nil {
panic(err)
}
}
func main() {
r := gin.Default()
r.POST("/employees/:id/update", func(c *gin.Context) {
id := c.Param("id")
newName := c.DefaultPostForm("name", "")
tx, err := db.Begin()
if err != nil {
c.JSON(500, gin.H{
"error": err,
})
return
}
defer tx.Rollback()
var oldName string
row := tx.QueryRow("SELECT name FROM employees WHERE id=?", id)
if err := row.Scan(&oldName); err != nil {
c.JSON(400, gin.H{
"error": err,
})
return
}
if oldName == newName {
c.JSON(200, gin.H{
"status": "success",
})
return
}
result, err := tx.Exec("UPDATE employees SET name=? WHERE id=? AND name=?", newName, id, oldName)
if err != nil {
c.JSON(400, gin.H{
"error": err,
})
return
}
affected, err := result.RowsAffected()
if err != nil {
c.JSON(400, gin.H{
"error": err,
})
return
}
if affected != 1 {
c.JSON(400, gin.H{
"error": "Optimistic lock failed",
})
return
}
if err := tx.Commit(); err != nil {
c.JSON(400, gin.H{
"error": err,
})
return
}
c.JSON(200, gin.H{
"status": "success",
})
})
r.Run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment