前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >golang 使用cgo访问mysql

golang 使用cgo访问mysql

作者头像
运维开发王义杰
发布2023-08-21 11:26:05
发布2023-08-21 11:26:05
30400
代码可运行
举报
运行总次数:0
代码可运行

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可以通过以下步骤完成:

更新系统软件包列表:

代码语言:javascript
代码运行次数:0
运行
复制

安装ODBC开发包:

代码语言:javascript
代码运行次数:0
运行
复制

下载和安装MySQL ODBC驱动程序:

上述命令中的驱动程序版本和文件名可能会因时间而异,你可以在https://dev.mysql.com/downloads/connector/odbc/上找到适合的版本。

代码语言:javascript
代码运行次数:0
运行
复制
myodbc8a.so /usr/lib64/
代码语言:javascript
代码运行次数:0
运行
复制
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>是要连接的数据库名。

代码语言:javascript
代码运行次数:0
运行
复制
[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。

代码语言:javascript
代码运行次数:0
运行
复制
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驱动程序返回的错误信息。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维开发王义杰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档