初学Go, 项目使用Go配置地图信息,使用JSON文件配置的。在解析时发现Go对JSON支持的不是很方便,绕了一点弯路完成,顺手记录一下,或许以后还用的到。当然如果引入第三方包会方便很多。
JSON文件结构大致是这样的:
[
{
"channel": 1,
"colorbegin": 11730812,
"colorend": 11730812,
"fiber_pos": 0,
"index": 1,
"latitude": 37.69512581,
"longitude": 121.03210634,
"mark_name": "YK001",
"physical_pos": 0
},
{
"channel": 1,
"colorbegin": 11730812,
"colorend": 11730812,
"fiber_pos": 174,
"index": 2,
"latitude": 37.69453029,
"longitude": 121.03057064,
"mark_name": "YK002",
"physical_pos": 174
}
]
从文件顺序读出数据来,按顺序对index赋值,然后根据经纬度计算每个点距离起点的位置。
大致DEMO代码如下:
func readJson(file string) error {
content, err := os.ReadFile(file)
if err != nil {
return err
}
fmt.Println("file size is ", len(content))
var data []map[string]interface{}
if err := json.Unmarshal(content, &data); err != nil {
fmt.Println(err)
return err
}
fmt.Printf("data :%d, %+v \n", len(data), data[0])
//新json数组
var newDataArray []map[string]interface{}
var distance int32
var lastLng float64
var lastLan float64
distance = 0
lastLng = 0
lastLan = 0
for i := 0; i < len(data); i++ {
newData := map[string]interface{}{}
for k, v := range data[i] {
newData[k] = v
if i == 0 {
distance = 0
newData["index"] = i + 1
newData["physical_pos"] = distance
newData["fiber_pos"] = distance
lastLng = newData["latitude"].(float64)
lastLan = newData["longitude"].(float64)
newDataArray = append(newDataArray, newData)
} else {
f1 := newData["latitude"].(float64)
f2 := newData["longitude"].(float64)
temp := calculateDistance(f1, f2, lastLng, lastLan)
distance += temp
lastLng = f1
lastLan = f2
newData["index"] = i + 1
newData["physical_pos"] = distance
newData["fiber_pos"] = distance
newDataArray = append(newDataArray, newData)
}
}
t, err := json.MarshalIndent(newDataArray, "", "\t")
if err != nil {
fmt.Println(err)
return err
}
f2, err2 := os.Create("e:/visualmark2.ini")
if err2 != nil {
fmt.Println(err2)
return err2
}
w := bufio.NewWriter(f2)
w.WriteString(string(t))
w.Flush()
return err
}
重点在这一句:
var data []map[string]interface{}
if err := json.Unmarshal(content, &data); err != nil { fmt.Println(err)
return err
}
这样解析出来的是JSON数组。
然后数组的每一个元素:
newData := map[string]interface{}{}
for k, v := range data[i] {
newData[
k]
= v
这样是把原来数组的元素赋值给新的元素。
再重新索引和计算坐标。
再把数组重新转成json,每个数组元素后都可以换行:
t, err := json.MarshalIndent(newDataArray, "", "\t")
写到文件里。
里面有个计算两点间距的函数,网上有很多例子,我这里简单实现,误差比较大,用在地图展示还勉强:
const M_PI = 3.14159265358979323846
func calculateDistance(long1 float64, lat1 float64, long2 float64, lat2 float64) int32 {
var a, b, R float64
R = 6378137 // 地球半径
lat1 = lat1 * M_PI / 180.0
lat2 = lat2 * M_PI / 180.0
a = lat1 - lat2
b = (long1 - long2) * M_PI / 180.0
var sa2, sb2 float64
sa2 = math.Sin(a / 2.0)
sb2 = math.Sin(b / 2.0)
distance := 2 * R * math.Asin(math.Sqrt(sa2*sa2+math.Cos(lat1)*math.Cos(lat2)*sb2*sb2))
return int32(distance)
}
短时间使用Go写了个小工具,感觉还是很不错的,和Python接近,某些方面不如Python方便,主要是对第三库还不熟悉。不过在TCP和HTTP服务方面要好的多,下一步准备把几个轻量级的C++ TCP服务使用Go重新实现一下。之前是使用POCO库实现的,使用起来也很简单,不过考虑GO做分布式服务和云服务更方便, 后期新项目准备使用Go。