记一次go语言中“:=“与“=“错误使用导致的问题

问题:使用gin框架查询mysql中一行数据报错

  • 报错内容:panic: runtime error: invalid memory address or nil pointer dereference
    在这里插入图片描述
  • 代码如下:
    package main
    
    import (
    	"database/sql"
    	"fmt"
    	_ "github.com/go-sql-driver/mysql" // init
    	"time"
    )
    
    var db *sql.DB
    
    func initMySQL() (err error) {
    	// DSN:Data Source Name
    	dsn := "root:yonbip2021!@tcp(127.0.0.1:3307)/sql_demo"
    	// 去初始化全局的db对象,而不是新声明一个db变量
    	db, err := sql.Open("mysql", dsn)
    	if err != nil {
    		panic(err)
    	}
    	// 尝试与数据库建立连接(校验dsn是否正确)
    	err = db.Ping()
    	if err != nil {
    		fmt.Printf("connect to db failed, err: %v\n", err)
    		return
    	}
    	// 数值需要业务具体情况来确定
    	db.SetConnMaxLifetime(time.Second * 10)	//
    	db.SetMaxOpenConns(200)	//最大连接数
    	db.SetMaxIdleConns(10)	// 最大空闲连接数
    	return
    }
    
    type user struct {
    	id int
    	age int
    	name string
    }
    
    // 查询单条数据示例
    func queryRowDemo() {
    	sqlStr := "select id, name, age from user where id=?"
    	var U user
    	// 非常重要:确保QueryRow之后调用Scan方法,否则持有的数据库链接不会被释放
    	err := db.QueryRow(sqlStr, 1).Scan(&U.id, &U.name, &U.age)
    	if err != nil {
    		fmt.Printf("scan failed, err:%v\n", err)
    		return
    	}
    	fmt.Printf("id:%d name:%s age:%d\n", U.id, U.name, U.age)
    }
    
    func main() {
    	if err := initMySQL();err != nil {
    		fmt.Printf("connect to db failed, err:%v\n", err)
    	}
    	// Close()用来释放掉数据库连接相关的资源
    	// 做完错误检查之后,确保db不为nil
    	defer db.Close()	// 注意这行代码要写在上面err判断的下面
    	fmt.Println("connect to db success")
    	// db.xx() 去使用数据库操作
    	queryRowDemo()
    }
    

排查过程:

  • 报错内容中已经打印出“connect to db success”,证明在59行以前,代码是没有问题的。所以我在61行打了断点,查看queryRowDemo函数的具体执行过程
    在这里插入图片描述

  • 当debug进行到queryRowDemo函数的底44行时,问题出现了,db(指针类型的问题接收者)的值为nil,但是可以看到在第10行定义了一个全局的sql.DB类型db变量,照理说不应该为nil才对,初步猜测是在哪里被覆盖了。

  • 查看在queryRowDemo()函数之前执行的initMysql()函数,有一行代码(16行)引起了我的注意

    db, err := sql.Open("mysql", dsn)
    
  • 这行代码对db重新做了初始化(:=),而不是赋值(=),到这里为什么db为nil就有了结论。

  • 将16行代码的":=“改为”="后重新执行,运行成功:
    在这里插入图片描述
    总结:

  • go语言中=与:=分别表示赋值和初始化,使用的时候要注意不要写错

  • 看不出代码问题的时候熟练使用debug能帮助你快速解决问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值