日期:2014-05-16  浏览次数:20711 次

golang ODBC 访问access数据库(问题解决之心理路程)

最近项目需要,需要操作access,以前是用VC++ OLE访问,网络用ACE库,感觉很庞大。。。决定用go试试


网上用的最多的就是这个https://github.com/weigj/go-odbc


安装方式如下:

ODBC database driver for Go

Install:
	cd $GOPATH/src
	git clone git://github.com/weigj/go-odbc.git odbc
	cd odbc
	go install


测试时碰到好多坑。。。。。


第1次当运行go install时,

坑爹1:发现找不到gcc,哦, 推测cgo去链接odbc32的dll,需要gcc编译环境,幸亏哥搞cocos2d-x时电脑上已经装了庞大的cygwin,于是启动Cygwin Terminal,跳转到odbc目录,


第2次当运行go install时,

坑爹2:提示access limit。。可是在console里直接运行gcc -v是存在的,感觉是gcc这个是linux的符号链接,推测go install时可能没用利用cygwin的环境设置,有点冲突,于是删掉gcc这个符号link,把真正的gcc-4.exe改名为gcc.exe,

第3次当运行go install时,

坑爹3:提示找不到ODBC的函数符号,你妹,不得不fuck source code了,读源码odbc.go,发现导入有个macro定义,
#ifdef __MINGW32__
  #include <windef.h>
#else
  typedef void* HANDLE;
#endif
原来odbc.go编译依赖MINGW环境,于是下载mingw,安装完后,把mingw的bin目录加到系统path里,编译成功。

go run 下面的例子代码,

package main

import (
	"database/sql"
	"fmt"
	_ "odbc/driver"
)

func main() {
	conn, err := sql.Open("odbc", "driver={Microsoft Access Driver (*.mdb)};dbq=d:\\test.mdb")
	if err != nil {
		fmt.Println("Connecting Error")
		return
	}
	defer conn.Close()
	stmt, err := conn.Prepare("select * from test") //ALTER TABLE tb ALTER COLUMN aa Long
	if err != nil {
		fmt.Println("Query Error")
		return
	}
	defer stmt.Close()
	row, err := stmt.Query()
	if err != nil {
		fmt.Print(err)
		fmt.Println("Query Error")
		return
	}
	defer row.Close()
	for row.Next() {
		var ID string
		var SequenceNumber int
		var ValueCode string
		if err := row.Scan(&ID, &SequenceNumber, &ValueCode); err == nil {
			fmt.Println(ID, SequenceNumber, ValueCode)
		}
	}
	fmt.Printf("%s\n", "finish")
	return
}

坑爹4:居然提示
fatal error: malloc/free - deadlock
	[signal 0xc0000005 code=0x1 addr=0x2f0 pc=0x419258]
	
	goroutine 1 [syscall]:
	[fp=0x10815fc] return()
		C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist465310315/go/src/pkg/runtime/asm_386.s:472
	[fp=0x1081624] runtime.cgocall(0x470a23, 0x1081630)
		C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist465310315/go/src/pkg/runtime/cgocall.c:162 +0x10a
	[fp=0x1081630] odbc._Cfunc_SQLFreeHandle(0x400003, 0xb115e8, 0x1081650)
		C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/go-build619492171/odbc/_obj/_cgo_defun.c:144 +0x31
	[fp=0x1081640] odbc.(*Statement).free(0x2f860140)
		odbc.go:745 +0x32
	[fp=0x1081648] odbc.(*Statement).Close(0x2f860140)
		odbc.go:752 +0x28
	[fp=0x1081650] odbc/driver.(*stmt).Close(0x2f860148, 0x2f8601c8, 0x405a2b)
		E:/go/src/odbc/driver/sql.go:107 +0x2a
	[fp=0x108168c] database/sql.(*DB).noteUnusedDriverStatement(0x2f884300, 0x2f8821e0, 0x2f882240, 0x2f860148)
		C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist465310315/go/src/pkg/database/sql/sql.go:554 +0x17a
	[fp=0x10816d0] database/sql.(*Stmt).finalClose(0x2f8862d0, 0x2f8601b8, 0x0)
		C:/Users/ADMINI~1/AppData/Local/Temp/2/bindis