You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言短链接服务:长/短URL无法存入MySQL数据库求助

短链接服务无法写入MySQL数据库的问题修复

核心问题与修复点

你的代码存在几个关键问题导致数据无法写入数据库,逐一修复如下:


1. 全局DB变量被局部覆盖

main函数里重新声明了局部变量db,导致全局的var db *sql.DB始终为nil,addLink中调用数据库方法时会直接报错。
修复:
直接赋值给全局变量,不要重新声明:

var db *sql.DB // 全局变量

func main(){
    var err error
    // 去掉var,直接给全局db赋值
    db, err = sql.Open("mysql", dsn()) 
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    // 添加Ping验证数据库连接是否真正建立
    if err := db.Ping(); err != nil {
        fmt.Println("数据库连接失败:", err.Error())
        return
    }
    fmt.Printf("已连接到MySQL服务器\n%s\n", dsn())
    defer db.Close()

    // 其余代码不变...
}

2. 数据库代码永远不会执行

addLink中在返回响应后写了return,后续的数据库操作代码完全不会运行,这是最核心的问题。
修复:
调整代码顺序,先执行数据库写入,再返回响应:

3. 插入参数顺序错误+错误的存储值

你要存储的是长URL和短URL标识,但代码里传的是genString(短标识)和linkString(HTML标签),完全不符合预期。
修复:
传入正确的长URL和短URL值,同时修正SQL语句的规范写法:

4. 错误的连接关闭时机

addLink里的defer db.Close()会在每次请求后关闭数据库连接,导致后续请求无法使用数据库,main函数里已经有全局的连接关闭逻辑,这里不需要重复。


修正后的addLink函数

func addLink(w http.ResponseWriter, r *http.Request) {
    log.Println("Add Link")
    key, ok := r.URL.Query()["ik"]
    if !ok || len(key) == 0 {
        w.WriteHeader(http.StatusBadRequest)
        fmt.Fprintf(w, "Failed to add link")
        return
    }

    longUrl := key[0]
    if !validLink(longUrl) {
        w.WriteHeader(http.StatusBadRequest)
        fmt.Fprintf(w, "Could not create shortlink need absolute path link.")
        return
    }

    // 检查长链接是否已存在(修正之前的逻辑错误)
    if _, exists := linkList[longUrl]; exists {
        w.WriteHeader(http.StatusConflict)
        fmt.Fprintf(w, "Already have this link")
        return
    }

    genString := randomString(5)
    shortUrl := fmt.Sprintf("hpe/%s", genString)
    linkList[genString] = longUrl

    // 执行数据库插入
    result, err := db.Exec("INSERT INTO Url (LongUrl, ShortUrl) VALUES (?, ?);", longUrl, shortUrl)
    if err != nil {
        fmt.Printf("数据库插入错误: %v\n", err)
        w.WriteHeader(http.StatusInternalServerError)
        fmt.Fprintf(w, "Failed to save link to database")
        return
    }
    // 可选:获取插入ID
    if _, err := result.LastInsertId(); err != nil {
        fmt.Printf("获取插入ID失败: %v\n", err)
    }

    // 返回响应
    w.Header().Set("Content-Type", "text/html")
    w.WriteHeader(http.StatusAccepted)
    linkString := fmt.Sprintf("<a href=\"%s\">%s</a>", shortUrl, shortUrl)
    fmt.Fprintf(w, "Added shortlink\n")
    fmt.Fprintf(w, linkString)
}

额外建议

  • 可以给genString添加唯一性检查,避免生成重复的短标识
  • 如果担心数据库写入延迟影响响应速度,可以将数据库操作放入goroutine,但要注意错误处理

内容的提问来源于stack exchange,提问作者expert.free

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 13:55:18