go程序运行Spaitalite踩坑记录

news2025/3/16 13:13:52

Spatialite参考资料:8.1. 开源地理空间数据库 — Python与开源GIS

Ubuntu安装SpaitaLite:

apt-get install libspatialite7 libsqlite3-mod-spatialite
apt-get install spatialite-bin

命令行打开数据库:spatialite xxx.db
执行一个空间函数:

SELECT ST_Distance(
GeomFromText('POINT(113.324521 23.1064289)'),
GeomFromText('POINT(113.307392 23.387375)')
);

windows安装,下载地址:Index of /gaia-sins/windows-bin-amd64
解压后目录配置到环境变量path中即可
(注意spatialite-tools和mod_spatialite两个都需要,spatialite-tools包含spatialite命令行工具,mod_spatialite里面dll是运行go、python程序所需要的)

go操作spatialite驱动:GitHub - briansorahan/spatialite: database/sql driver for libspatialite
添加依赖:go get -u github.com/briansorahan/spatialite

gorm操作spatialite示例代码:

package main
 
import (
    "fmt"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)
 
import (
    _ "github.com/briansorahan/spatialite"
)
 
func main() {
    sqliteDialector := sqlite.Dialector{
        DriverName: "spatialite",
        DSN:        "./spatialite.db",
    }
    db, err := gorm.Open(sqliteDialector, &gorm.Config{})
    if err != nil {
        fmt.Println(fmt.Sprintf("open database error: %v", err))
        return
    }
 
    var ff float64
    rs := db.Raw("SELECT ST_Distance(GeomFromText('POINT(113.324521 23.1064289)'),GeomFromText('POINT(113.307392 23.387375)'))").Scan(&ff)
    if rs.Error != nil {
        fmt.Println(fmt.Sprintf("SELECT ST_Distance error: %v", rs.Error))
        return
    }
    fmt.Println(fmt.Sprintf("ST_Distance: %v", ff))
}

这里使用spatialite驱动连接sqlite数据库,并执行一个空间函数

报错解决:

报错一:
/root/go/pkg/mod/github.com/briansorahan/spatialite@v0.0.0-20200320201955-49400a1f7714/driver.go:6:11: fatal error: sqlite3.h: No such file or directory 6 | // #include <sqlite3.h>
报错二:
/root/go/pkg/mod/github.com/briansorahan/spatialite@v0.0.0-20200320201955-49400a1f7714/driver.go:7:11: fatal error: spatialite.h: No such file or directory 7 | // #include <spatialite.h>
 
这里报错是由于驱动依赖本地C库,所以需要安装好对应的库
 
linux本地库安装:
sudo apt install sqlite3 libsqlite3-dev
sudo apt install libspatialite-dev
 
windows:下载相应头文件,并配置CGO_CFLAGS环境变量
我这里直接使用QGIS中带的头文件,将需要的头文件提取出来放到单独的spatialite-include目录(对应资源放到附件中)
然后配置环境变量CGO_CFLAGS=-ID:\spatialite-include (我这里是spatialite-include直接放D盘,记得换成自己的目录)

这里驱动存在一个bug,第二次开始运行会有个报错:InitSpatiaMetaData() error:"table spatial_ref_sys already exists" 
这是由于驱动中代码,每次打开数据库连接时都会执行SELECT InitSpatialMetaData(1)导致
不过这个报错并不影响程序正常运行,可以暂时先无视,后续有空再解决


踩坑记录:

前面不小心下载错mod_spatialite,下载成了32位版本的,导致每次运行都会报: not an error,根本看不出啥问题
然后一路跟踪报错,定位到报错代码在sqlite3_load_extension.go中调用C代码处:C.sqlite3_load_extension

这里C.sqlite3_load_extension的方法在sqlite3.h中定义,打开sqlite3.h文件,找到sqlite3_load_extension方法:

/*
** CAPI3REF: Load An Extension
** METHOD: sqlite3
**
** ^This interface loads an SQLite extension library from the named file.
**
** ^The sqlite3_load_extension() interface attempts to load an
** [SQLite extension] library contained in the file zFile.  If
** the file cannot be loaded directly, attempts are made to load
** with various operating-system specific extensions added.
** So for example, if "samplelib" cannot be loaded, then names like
** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
** be tried also.
**
** ^The entry point is zProc.
** ^(zProc may be 0, in which case SQLite will try to come up with an
** entry point name on its own.  It first tries "sqlite3_extension_init".
** If that does not work, it constructs a name "sqlite3_X_init" where the
** X is consists of the lower-case equivalent of all ASCII alphabetic
** characters in the filename from the last "/" to the first following
** "." and omitting any initial "lib".)^
** ^The sqlite3_load_extension() interface returns
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
** ^If an error occurs and pzErrMsg is not 0, then the
** [sqlite3_load_extension()] interface shall attempt to
** fill *pzErrMsg with error message text stored in memory
** obtained from [sqlite3_malloc()]. The calling function
** should free this memory by calling [sqlite3_free()].
**
** ^Extension loading must be enabled using
** [sqlite3_enable_load_extension()] or
** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL)
** prior to calling this API,
** otherwise an error will be returned.
**
** <b>Security warning:</b> It is recommended that the
** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this
** interface.  The use of the [sqlite3_enable_load_extension()] interface
** should be avoided.  This will keep the SQL function [load_extension()]
** disabled and prevent SQL injections from giving attackers
** access to extension loading capabilities.
**
** See also the [load_extension() SQL function].
*/
SQLITE_API int sqlite3_load_extension(
  sqlite3 *db,          /* Load the extension into this database connection */
  const char *zFile,    /* Name of the shared library containing extension */
  const char *zProc,    /* Entry point.  Derived from zFile if 0 */
  char **pzErrMsg       /* Put error message here if not 0 */
);

这里注释明确说明应该使用pzErrMsg来获取错误信息,但是go代码中却使用sqlite3_errmsg来获取,所以导致返回:not an error

对这里代码做简单的改造:

var errMsg *C.char
defer C.sqlite3_free(unsafe.Pointer(errMsg)) // 确保释放错误信息的内存
 
fmt.Println("Loading extension: %s", C.GoString(cext))
rv = C.sqlite3_load_extension(c.db, cext, nil, &errMsg)
if rv != C.SQLITE_OK {
    if errMsg != nil {
        fmt.Println("sqlite3_load_extension error: ", C.GoString(errMsg))
    }
    C.sqlite3_enable_load_extension(c.db, 0)
    return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
}

再重新运行,获取到真正的报错:

至此才终于定位到是下载的dll文件问题,重新下载64位版本的终于解决

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2316038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Everything搜索工具下载使用教程(附安装包),everything搜索工具文件快速查找

文章目录 前言一、Everything搜索工具下载二、Everything搜索工具下载使用教程 前言 Everything搜索工具能凭借文件名实时精准定位文件&#xff0c;接下来的教程&#xff0c;将详细为你呈现 Everything搜索工具的下载及使用方法&#xff0c;助你开启高效文件搜索的便捷之旅 。…

LeetCode 解题思路 17(Hot 100)

解题思路&#xff1a; 找到链表中点&#xff1a; 使用快慢指针法&#xff0c;快指针每次移动两步&#xff0c;慢指针每次移动一步。当快指针到达末尾时&#xff0c;慢指针指向中点。递归分割与排序&#xff1a; 将链表从中点处分割为左右两个子链表&#xff0c;分别对这两个子…

Qt程序基于共享内存读写CodeSys的变量

文章目录 1.背景2.结构体从CodeSys导出后导入到C2.1.将结构体从CodeSys中导出2.2.将结构体从m4文件提取翻译成c格式 3.添加RTTR注册信息4.读取PLC变量值5.更改PLC变量值 1.背景 在文章【基于RTTR在C中实现结构体数据的多层级动态读写】中&#xff0c;我们实现了通过字符串读写…

7-12 关于堆的判断

输入样例&#xff1a; 5 4 46 23 26 24 10 24 is the root 26 and 23 are siblings 46 is the parent of 23 23 is a child of 10输出样例&#xff1a; F T F T 这题是建最小堆&#xff0c;数据结构牛老师讲过这个知识点&#xff0c;但是我给忘了&#xff0c;补题搜了一下才解…

STM32 HAL库实战:高效整合DMA与ADC开发指南

STM32 HAL库实战&#xff1a;高效整合DMA与ADC开发指南 一、DMA与ADC基础介绍 1. DMA&#xff1a;解放CPU的“数据搬运工” DMA&#xff08;Direct Memory Access&#xff09; 是STM32中用于在外设与内存之间直接传输数据的硬件模块。其核心优势在于无需CPU干预&#xff0c;…

正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-4 uboot目录分析

前言&#xff1a; 本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。 引用&#xff1a; …

Unity开发——点击事件/射线检测

一、IPointerClickHandler接口 通过为 UI 元素添加自定义脚本&#xff0c;实现IPointerClickHandle接口&#xff0c;在点击事件发生时进行处理。 这种方式适用于对特定 UI 元素的点击检测。 using UnityEngine; using UnityEngine.EventSystems;public class UIClickHandler…

【零基础入门unity游戏开发——unity3D篇】3D物理系统之 —— 3D刚体组件Rigidbody

考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…

55年免费用!RevoUninstaller Pro专业版限时领取

今天&#xff0c;我要给大家介绍一款超给力的卸载工具——RevoUninstaller Pro。这是一款由保加利亚团队精心打造的专业级卸载软件&#xff0c;堪称软件卸载界的“神器”。 RevoUninstaller分为免费版和专业版。专业版功能更为强大&#xff0c;但通常需要付费才能解锁全部功能。…

基于ensp的IP企业网络规划

基于ensp的IP企业网络规划 前言网络拓扑设计功能设计技术详解一、网络设备基础配置二、虚拟局域网&#xff08;VLAN&#xff09;与广播域划分三、冗余协议与链路故障检测四、IP地址自动分配与DHCP相关配置五、动态路由与安全认证六、广域网互联及VPN实现七、网络地址转换&#…

谷歌Chrome或微软Edge浏览器修改网页任意内容

在谷歌或微软浏览器按F12&#xff0c;打开开发者工具&#xff0c;切换到console选项卡&#xff1a; 在下面的输入行输入下面的命令回车&#xff1a; document.body.contentEditable"true"效果如下&#xff1a;

初探大模型开发:使用 LangChain 和 DeepSeek 构建简单 Demo

最近&#xff0c;我开始接触大模型开发&#xff0c;并尝试使用 LangChain 和 DeepSeek 构建了一个简单的 Demo。通过这个 Demo&#xff0c;我不仅加深了对大模型的理解&#xff0c;还体验到了 LangChain 和 DeepSeek 的强大功能。下面&#xff0c;我将分享我的开发过程以及一些…

【Linux】进程(1)进程概念和进程状态

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;Linux 目录 前言 一、什么是进程 二、task_struct的内容 三、Linux下进程基本操作 四、父进程和子进程 1. 用fork函数创建子进程 五、进程状态 1. 三种重…

关闭win11根据内容自动调整屏幕亮度

在win11笔记本上使用编程软件的时候&#xff0c;用的是深色背景&#xff0c;但是屏幕会慢慢变暗&#xff1b;等切换回明亮的桌面时&#xff0c;又会慢慢变亮&#xff0c;带来不适应的感觉。这个博客记录一下解决这个问题的办法 ps&#xff1a;有些人修改的是电源选项&#xff…

2021-05-23 C++百元百鸡

此是草稿&#xff0c;有值得优化的地方&#xff0c;如从公鸡先循环再母鸡再小鸡这样可以提高效率&#xff0c;且有输出后也可优化为公鸡母鸡小鸡初始化。 void 百元百鸡() {//缘由https://ask.csdn.net/questions/7434093?spm1005.2025.3001.5141int xj 1, mj 1, gj 1, y …

Android自动化测试工具

细解自动化测试工具 Airtest-CSDN博客 以下是几种常见的Android应用自动化测试工具&#xff1a; Appium&#xff1a;支持多种编程语言&#xff0c;如Java、Python、Ruby、JavaScript等。可以用于Web应用程序和原生应用程序的自动化测试&#xff0c;并支持iOS和Android平台。E…

【蓝桥杯】24省赛:数字串个数

思路 本质是组合数学问题&#xff1a; 9个数字组成10000位数字有9**10000可能 不包括3的可能8**10000 不包括7的可能8**10000 既不包括3也不包括77**10000 根据容斥原理&#xff1a;结果为 9 ∗ ∗ 10000 − 8 ∗ ∗ 10000 − 8 ∗ ∗ 10000 7 ∗ ∗ 10000 9**10000 - 8**10…

SpringBoot中使用kaptcha生成验证码

简介 kaptcha是谷歌开源的简单实用的验证码生成工具。通过设置参数&#xff0c;可以自定义验证码大小、颜色、显示的字符等等。 Maven引入依赖 <!-- https://mvnrepository.com/artifact/pro.fessional/kaptcha --><dependency><groupId>pro.fessional<…

蓝桥杯嵌入式赛道复习笔记1(led点亮)

前言 基础的文件创建&#xff0c;参赛资源代码的导入&#xff0c;我就不说了&#xff0c;直接说CubeMX的配置以及代码逻辑思路的书写&#xff0c;在此我也预祝大家人人拿国奖 理论讲解 原理图简介 1.由于存在PC8引脚到PC15引脚存在冲突&#xff0c;那么官方硬件给的解决方案…

六十天前端强化训练之第十七天React Hooks 入门:useState 深度解析

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、知识讲解 1. Hooks 是什么&#xff1f; 2. useState 的作用 3. 基本语法解析 4. 工作原理 5. 参数详解 a) 初始值设置方式 b) 更新函数特性 6. 注意事项 7. 类组…