定义一个接口,然后定义一个类去实现这些接口函数,然后这个类中保存了一个sql.DB对象指针,在打开成功之后,将这个句柄保存在这个对象指针后,返回到调用函数时,这时这个接口的sql.DB对象指针为空。然后程序崩溃。
接口如下:
package storage
type Storage interface {
Open(string) error
Close()error
}
实现类:
package storage
import (
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
"log"
)
type Sqlite struct {
db *sql.DB
}
func (m Sqlite) Open(args string)error {
var err error
m.db, err = sql.Open("sqlite3", args)
if nil != err {
log.Println(err)
return err
}
defer func() {
if nil != m.db {
fmt.Println("this is a test")
}
}()
return nil
}
func (m Sqlite)Close()error {
if nil != m.db {
m.db.Close()
}else {
fmt.Println("close fail")
}
return nil
}
main.go
package main
import (
"interface/storage"
)
func main() {
var s storage.Storage
s = storage.Sqlite{}
s.Open("foo.db")
s.Close()
}
结果为close fail。?明显我们打开是成功的。找了半天没看到相应资料。
最后自己想了下
func (m Sqlite) Open(args string)error
估计是这里的m是值传递不会改变外面的数据。
然后将上面的sqlite.go改了下
package storage
import (
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
"log"
)
type Sqlite struct {
db *sql.DB
}
func (m *Sqlite) Open(args string)error {
var err error
m.db, err = sql.Open("sqlite3", args)
if nil != err {
log.Println(err)
return err
}
defer func() {
if nil != m.db {
fmt.Println("this is a test")
}
}()
return nil
}
func (m *Sqlite)Close()error {
if nil != m.db {
m.db.Close()
}else {
fmt.Println("close fail")
}
return nil
}
编译报错:
再修改下main.go
package main
import (
"interface/storage"
)
func main() {
var s storage.Storage
s = new(storage.Sqlite)
s.Open("foo.db")
s.Close()
}
?看运行结果:
没有fail日志,问题就解决了。?
|