CGO是Go语言提供的一种机制,允许开发人员在Go代码中调用C语言函数,也可以将Go代码编译成共享库供C程序调用。CGO的全称是"C Go",意思是Go语言和C语言之间的交互。
使用CGO可以让Go语言更加灵活,因为在某些情况下,使用C语言编写的库可能比使用Go语言编写的库更加高效、稳定或具有更好的可移植性。使用CGO,可以在Go代码中调用C语言函数,也可以将Go代码编译成共享库供C程序调用。
在Go语言中,使用CGO需要使用import "C"语句引入C语言头文件,同时使用extern "C"声明C语言函数,这样Go语言就可以在运行时动态链接C语言库,并且使用C语言函数。
需要注意的是,使用CGO可能会导致程序的性能损失,并且在不同的操作系统和平台上,使用CGO可能需要不同的配置和参数。因此,在使用CGO时,需要谨慎评估其优缺点,并进行适当的优化和调试。
在centos上安装odbc
在CentOS上安装ODBC可以通过以下步骤完成:
更新系统软件包列表:
安装ODBC开发包:
下载和安装MySQL ODBC驱动程序:
上述命令中的驱动程序版本和文件名可能会因时间而异,你可以在https://dev.mysql.com/downloads/connector/odbc/上找到适合的版本。
myodbc8a.so /usr/lib64/
wget https://dev.mysql.com/get/Downloads/Connector-ODBC/8.0/mysql-connector-odbc-8.0.28-linux-glibc2.12-x86-64bit.tar.gz
tar -xzvf mysql-connector-odbc-8.0.28-linux-glibc2.12-x86-64bit.tar.gz
sudo cp mysql-connector-odbc-8.0.28-linux-glibc2.12-x86-64bit/lib/lib
配置ODBC数据源:
在/etc/odbc.ini文件中添加以下内容:
其中,<hostname>是MySQL服务器的主机名或IP地址,<port>是MySQL服务器的端口号,<username>和<password>是MySQL服务器的用户名和密码,<database>是要连接的数据库名。
[MySQLODBC]
Description=MySQL ODBC Driver
Driver=/usr/lib64/libmyodbc8a.so
Server=<hostname>
Port=<port>
User=<username>
Password=<password>
Database=<database>
完成上述步骤后,就可以使用ODBC连接到MySQL数据库了。
以下是一个使用cgo和ODBC访问MySQL数据库的示例程序。在运行此程序之前,需要先安装ODBC驱动程序和MySQL ODBC驱动程序,并将其配置为系统DSN。
package main
/*
#cgo CFLAGS: -I/usr/include
#cgo LDFLAGS: -lodbc
#include <sql.h>
#include <sqlext.h>
#include <stdlib.h>
#include <string.h>
// Declare a helper function to check for errors and print messages
void checkError(SQLRETURN ret, SQLHANDLE handle, SQLSMALLINT handleType) {
SQLINTEGER i = 0;
SQLINTEGER native;
SQLCHAR state[7];
SQLCHAR text[256];
SQLSMALLINT len;
SQLRETURN ret2;
while (SQL_SUCCESS == (ret2 = SQLGetDiagRec(handleType, handle, ++i, state, &native, text, sizeof(text), &len))) {
fprintf(stderr, "Error #%ld(%s): %s\n", (long)native, state, text);
}
}
// Declare a function to allocate a statement handle
SQLRETURN allocateStatementHandle(SQLHDBC conn, SQLHSTMT *stmt) {
SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, conn, stmt);
if (ret != SQL_SUCCESS) {
checkError(ret, conn, SQL_HANDLE_DBC);
}
return ret;
}
// Declare a function to execute a query and return a result set handle
SQLRETURN executeQuery(SQLHSTMT stmt, const char *query, SQLHDBC conn, SQLHSTMT *result) {
SQLRETURN ret = allocateStatementHandle(conn, result);
if (ret != SQL_SUCCESS) {
return ret;
}
ret = SQLExecDirect(*result, (SQLCHAR*)query, SQL_NTS);
if (ret != SQL_SUCCESS) {
checkError(ret, *result, SQL_HANDLE_STMT);
}
return ret;
}
// Declare a function to close a statement handle
SQLRETURN closeStatementHandle(SQLHSTMT stmt) {
SQLRETURN ret = SQLFreeHandle(SQL_HANDLE_STMT, stmt);
if (ret != SQL_SUCCESS) {
checkError(ret, stmt, SQL_HANDLE_STMT);
}
return ret;
}
*/
import "C"
import (
"fmt"
"log"
)
func main() {
connStr := "DSN=MySQLODBC"
var conn C.SQLHDBC
ret := C.SQLAllocHandle(C.SQL_HANDLE_DBC, C.SQLHANDLE(C.SQL_NULL_HANDLE), &conn)
if ret != C.SQL_SUCCESS {
C.checkError(ret, C.SQLHANDLE(conn), C.SQL_HANDLE_DBC)
return
}
defer C.SQLFreeHandle(C.SQL_HANDLE_DBC, conn)
ret = C.SQLDriverConnect(conn, nil, (*C.SQLCHAR)(C.CString(connStr)), C.SQL_NTS, nil, 0, nil, C.SQL_DRIVER_COMPLETE)
if ret != C.SQL_SUCCESS {
C.checkError(ret, C.SQLHANDLE(conn), C.SQL_HANDLE_DBC)
return
}
var stmt C.SQLHSTMT
query := "SELECT * FROM mytable"
ret = C.executeQuery(stmt, C.CString(query), conn, &stmt)
if ret != C.SQL_SUCCESS {
C.checkError(ret, C.SQLHANDLE(stmt), C.SQL_HANDLE_STMT)
return
}
defer C.closeStatementHandle(stmt)
var id C.int
var name [50]C.char
for {
ret = C.SQLFetch(stmt)
if ret == C.SQL_SUCCESS || ret == C.SQL_SUCCESS_WITH_INFO {
C.SQLGetData(stmt, 1,
C.SQL_C_LONG, unsafe.Pointer(&id), 0, nil)
C.SQLGetData(stmt, 2, C.SQL_C_CHAR, unsafe.Pointer(&name), 50, nil)
fmt.Printf("id: %d, name: %s\n", id, C.GoString(&name[0]))
} else {
break
}
}
}
这个示例程序使用了cgo和ODBC API来连接到MySQL数据库,执行一个查询语句,并将结果打印到控制台上。
首先,我们需要在程序中包含ODBC相关的头文件,并且使用#cgo
指令来告诉C编译器在哪里可以找到ODBC库。然后,我们定义了一些C语言的辅助函数来分配和释放ODBC句柄,执行SQL查询,并处理错误消息。
在main
函数中,我们首先定义了一个DSN字符串,用于指定ODBC数据源的名称。然后,我们分配一个连接句柄,并使用SQLDriverConnect
函数连接到数据源。如果连接成功,则可以使用executeQuery
函数执行SQL查询,并获取结果集句柄。我们使用SQLFetch
函数逐行获取结果集中的数据,并使用SQLGetData
函数获取每个列的值,并将其打印到控制台上。
需要注意的是,ODBC API中的许多函数都具有异步执行的特性,因此需要在调用这些函数后检查返回值,以确定它们是否已经完成执行。如果需要获取错误消息,则可以调用SQLGetDiagRec
函数来获取ODBC驱动程序返回的错误信息。