登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  Golang >  Go教程

Go go-shp 怎样把点数据写成Shapefile

来源:17golang原创

时间:2026-10-31 02:19:39 371浏览 收藏

用 Go 写点数据时,可以把坐标放进 shp.Point,再用 shp.Create("points.shp", shp.POINT) 创建写入器。随后先用 SetFields 定义 DBF 属性字段,再对每个点分别调用 Write 和 WriteAttribute。写完后关闭 Writer,目录中会得到同名的几何、索引和属性文件。

官方资料:https://pkg.go.dev/github.com/jonas-p/go-shp

下面的示例只讨论点要素和简单字符串属性,不负责坐标投影转换,也不把示意图当成程序运行截图。

先分清 Shapefile 不是一个单独文件

一个可用的 Shapefile 通常是同名文件组:.shp 保存点、线或面的几何记录,.shx 保存几何记录的索引信息,.dbf 保存与要素行对应的属性字段。go-shp 的 Writer 会围绕你传入的主文件名处理这些组件,所以不要只把 points.shp 当成最终交付物。

坐标参考系统通常由旁边的 .prj 文件描述。当前写入示例只给出 X、Y 数值,go-shp 不会根据数值猜测经纬度或自动生成投影定义。若数据有明确坐标系,应由业务流程另外生成或提供正确的 .prj,并把它与前三个同名文件一起交付。

Go go-shp 从点数据和字段定义组成 Shapefile 文件组的静态结构图
图1:结构说明图,展示点坐标、Writer、DBF 字段与 Shapefile 文件组件的静态关系,不是运行截图。

安装依赖并选择 POINT 写入类型

在已有 Go 模块中安装包:

# 安装用于读取和写入 ESRI Shapefile 的 Go 包
go get github.com/jonas-p/go-shp

示例程序使用 shp.POINT 创建点类型 Writer。这里的类型要和后续传入的几何对象一致;如果输入的是折线或面,不能仍然使用点类型。

package main

import (
    "log"
    "strconv"

    shp "github.com/jonas-p/go-shp"
)

func main() {
    points := []shp.Point{
        {X: 116.3913, Y: 39.9075},
        {X: 121.4737, Y: 31.2304},
        {X: 113.2644, Y: 23.1291},
    }

    // 用 POINT 声明几何类型,文件名会成为同名文件组的基名。
    writer, err := shp.Create("points.shp", shp.POINT)
    if err != nil {
        log.Fatalf("创建 Shapefile 失败: %v", err)
    }
    defer writer.Close()

    // DBF 字段必须先定义,后续属性值按字段下标写入。
    fields := []shp.Field{
        shp.StringField("NAME", 32),
        shp.StringField("CODE", 16),
    }
    if err := writer.SetFields(fields); err != nil {
        log.Fatalf("设置属性字段失败: %v", err)
    }

    for row, point := range points {
        // 写入几何记录;返回值是库内部的记录编号,不替代属性行号管理。
        writer.Write(&point)

        // row 与几何记录保持同一顺序,两个字段分别写入 NAME 和 CODE。
        if err := writer.WriteAttribute(row, 0, "地点-"+strconv.Itoa(row+1)); err != nil {
            log.Fatalf("写入 NAME 失败: %v", err)
        }
        if err := writer.WriteAttribute(row, 1, "P"+strconv.Itoa(row+1)); err != nil {
            log.Fatalf("写入 CODE 失败: %v", err)
        }
    }
}

这个程序的关键不是把所有代码塞进一个循环,而是维持两条对应关系:每次 Write 写一个点,每次 WriteAttribute 用同一个 row 写该点的属性。字段下标 0 和 1 分别对应 SetFields 中的两个字段。

字段定义和点记录要保持同一套顺序

DBF 属性表是按字段数组建立的。字段名、字段类型和长度应该在写入前确定;字符串字段长度不要只按当前样例值设置,否则真实数据变长时容易出现截断或写入失败。需要数值或日期时,可以换用包提供的 NumberField、FloatField 或 DateField,但每个字段都应在设计阶段固定用途。

写属性时,row 表示要关联的要素行,field 是字段下标。不要在写完几何后用另一套排序写 DBF;例如点按时间排序、属性按名称排序,会让地图上的要素和属性错位。

Go go-shp 点记录索引、字段定义与 DBF 属性行的静态映射图
图2:关系说明图,展示 Point 记录、字段下标和 DBF 行之间的对应边界,不是并发运行证据。

关闭 Writer 后怎样整理交付文件

Close 是写入流程的一部分。示例用 defer writer.Close() 确保函数退出时关闭文件;如果是更复杂的批处理,可以在关闭后再把输出目录交给下一个处理阶段。不要在 Writer 仍未关闭时就复制、压缩或上传文件组。

交付前可以按以下清单整理:

文件用途本例是否由 Writer 负责
points.shp点几何记录是
points.shx几何索引和定位信息是
points.dbfNAME、CODE 等属性行是
points.prj坐标参考定义本例不自动生成

如果输出路径带目录,先确保目录存在;如果目标文件已经存在,按项目策略决定是覆盖、换文件名还是使用 shp.Append 追加。不要把旧的 .dbf 或 .shx 留在目录里冒充新结果。

常见问题和速查结论

为什么地图软件能打开 shp,却看不到属性?

通常是文件组不完整、DBF 字段没有正确写入,或者几何文件和属性文件来自不同一批数据。确认三个同名文件同时生成,并保持同一输出基名。

经纬度点写入后位置不对怎么办?

go-shp 只接收 X、Y 数值,不会替你判断坐标顺序或投影坐标系。先确认输入是经度在前、纬度在后,还是已经投影的平面坐标;再为文件组补上与数据一致的 .prj。

能不能只保存 shp 文件?

不建议。Shapefile 的实用交付单位是同名文件组,属性需求还需要 DBF,空间索引通常需要 SHX;缺少配套文件会降低兼容性。

写点和写属性哪个先调用?

推荐在同一轮中先写几何,再用同一行号写属性,最容易保持对应关系。关键是字段已经通过 SetFields 定义,并且所有记录使用稳定的行顺序。

结语

把 Go 点数据写成 Shapefile 的最小路径是:创建 POINT Writer,定义字段,逐条写入 shp.Point 和属性,关闭 Writer,再把同名文件组与正确的坐标参考说明一起交付。只要把几何记录、DBF 行号和字段下标固定在同一套顺序里,后续接入地图软件或批处理流程就不会因为属性错位而返工。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>