go官方驱动地址:https://download.dameng.com/eco/adapter/resource/go/dm-go-driver.zip
代码在n.go:L632
:
func (dc *DmConnection) queryContext(ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
...
if args != nil && len(args) > 0 {
stmt, err := dc.prepare(query)
if err != nil {
stmt.close()
return nil, err
}
dc.lastExecInfo = stmt.execInfo
stmt.innerUsed = true
return stmt.queryContext(ctx, args)
}
...
}
func (dc *DmConnection) prepare(query string) (*DmStatement, error) {
err := dc.checkClosed()
if err != nil {
return nil, err
}
stmt, err := NewDmStmt(dc, query)
if err != nil {
return nil, err
}
err = stmt.prepare()
return stmt, err
}
上述代码中,如果prepare
失败,很可能返回的stmt
是nil
,这时候去调用stmt.close
就会panic
掉。
因此,建议这样修改:
func (dc *DmConnection) queryContext(ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
...
if args != nil && len(args) > 0 {
stmt, err := dc.prepare(query)
defer func(){
if stmt != nil {
stmt.close()
}
}()
if err != nil {
return nil, err
}
dc.lastExecInfo = stmt.execInfo
stmt.innerUsed = true
return stmt.queryContext(ctx, args)
}
...
}
因为官方代码没开源,不知道哪个地方能提issue,就在这里反馈了。
由于在err
不为nil
的情况下,prepare
既可能返回nil
,也有可能返回一个具体的实例,因此很多调用prepare
函数的地方都是不严谨的,建议好好优化一下。