Golang 中關於 cgo 的文檔比較少,所以我絕對寫個簡單的案例,這裡用 Mysql 做案例,一種是調用C裡邊的函數,一種是完全用 golang 來點用 mysql 庫函數。我的環境是 MAC ,如果測試的話,請 LDFLAGS 對應自己的環境編寫。
注意的地方
Golang 的 cgo 引用必須單獨一行,也就是說必須如下寫法
import "C"
cgo 中 沒有 C.NULL 類型 ,所以你要使用 nil
package main
/*
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "/usr/local/mysql/include/mysql.h"
MYSQL *mysql,*res;
MYSQL_RES *results;
MYSQL_FIELD *field;
struct Person {
char *name;
int age;
int height;
int weight;
};
#cgo darwin LDFLAGS: -I/usr/local/mysql/include -L/usr/local/mysql/lib -lmysqlclient
void get_mysql_query()
{
MYSQL_ROW row;
mysql = mysql_init(NULL);
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client");
res = mysql_real_connect(mysql, "127.0.0.1","root","dgj99349", "myblog", 0,NULL,0);
if ( mysql_query(res, "SELECT * FROM wp_users")){
fprintf(stderr,"Query failed (%s)/n",mysql_error(res));
exit(1);
}
if (!(results=mysql_store_result(res))) {
fprintf(stderr,"Couldn't get result from %s/n", mysql_error(res));
exit(1);
}
int number = mysql_num_fields(results);
while( ( row = mysql_fetch_row(results) ) ) {
for ( int i = 0; i < number; i++ )
{
if( (field = mysql_fetch_field(results) )!=NULL ){
printf("field_name is : %s , field_value is : %s \n", field->name,row[i]);
}
}
}
mysql_free_result(results);
mysql_close(mysql);
mysql_server_end();
return;
}
*/
import "C"
import "fmt"
import "unsafe"
const (
maxSize = 1 << 20
)
func main() {
C.puts(C.CString(" C MYSQL 函數查詢…… "))
C.get_mysql_query()
C.puts(C.CString(" C MYSQL 使用庫函數查詢…… "))
// 使用C的函數庫 初始化 MYSQL *
mysql := C.mysql_init(nil);
// 使用庫連接 MYSQL *
C.mysql_real_connect(mysql, C.CString("127.0.0.1"),C.CString("root"),C.CString("dgj99349"), C.CString("myblog"), 0,nil,0);
// 查詢函數 int
C.mysql_query(mysql,C.CString("SELECT * FROM wp_users"))
// 查詢結果 MYSQL_RES *
results := C.mysql_store_result(mysql)
// 查詢的字段數目 unsigned int
number := C.mysql_num_fields(results);
// 查詢結果 char **MYSQL_ROW
row := C.mysql_fetch_row(results)
// 查詢的字段結果 MYSQL_FIELD *
field := C.mysql_fetch_field(results)
// 每個字段的內容的長度 unsigned long
sql_lengths := C.mysql_fetch_lengths(results)
lengths := (*[maxSize]uint64)(unsafe.Pointer(sql_lengths))
cfields := (*[maxSize]C.MYSQL_FIELD)(unsafe.Pointer(field))
rowPtr := (*[maxSize]*[maxSize]byte)(unsafe.Pointer(row))
for i := 0; i < int(number); i++ {
length := cfields[i].name_length
fname := (*[maxSize]byte)(unsafe.Pointer(cfields[i].name))[:length]
fmt.Print("field_name is :",string(fname))
fmt.Println(" ,field_value is : ",string(rowPtr[i][:lengths[i]]))
}
// 釋放結果
C.mysql_free_result(results);
// 關閉mysql
C.mysql_close(mysql);
C.mysql_server_end();
}