golang map用法 https://ashitani.jp/golangtips/tips_map.html
* map.go
package main
import (
"encoding/json"
"log"
"fmt"
)
func main() {
var provinceList []interface{}
var districtList []interface{}
var province map[string]interface{}
var m map[string]interface{}
m = make(map[string]interface{})
m["name"] = "安庆"
m["items"] = [...]string{"大观区","怀宁县","潜山县","宿松县","太湖县","桐城市","望江县","宜秀区","迎江区","岳西县"}
districtList = append(districtList, m)
m = make(map[string]interface{})
m["name"] = "蚌埠"
m["items"] = [...]string{"龙子湖区","固镇县","怀远县","淮上区","五河县","禹会区","蚌山区"}
districtList = append(districtList, m)
province = make(map[string]interface{})
province["name"] = "安徽"
province["items"] = districtList
provinceList = append(provinceList, province)
jsonStr, err := json.Marshal(provinceList)
if err!=nil{
log.Fatal(err)
return
}
fmt.Printf("%s\n",jsonStr)
}
* test:
$ go run map.go
[{"items":[{"items":["大观区","怀宁县","潜山县","宿松县","太湖县","桐城市","望江县","宜秀区","迎江区","岳西县"],"name":"安庆"},{"items":["龙子湖区","固镇县","怀远县","淮上区","五河县","禹会区","蚌山区"],"name":"蚌埠"}],"name":"安徽"}]
格式化:
[{
"items": [{
"items": ["大观区", "怀宁县", "潜山县", "宿松县", "太湖县", "桐城市", "望江县", "宜秀区", "迎江区", "岳西县"],
"name": "安庆"
}, {
"items": ["龙子湖区", "固镇县", "怀远县", "淮上区", "五河县", "禹会区", "蚌山区"],
"name": "蚌埠"
}],
"name": "安徽"
}]
* 建表语句
CREATE TABLE `W_DistrictInfo` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`districtname` varchar(50) NOT NULL DEFAULT '',
`districtcode` varchar(20) NOT NULL DEFAULT '',
`parentid` mediumint(8) NOT NULL DEFAULT '0',
`path` varchar(30) NOT NULL DEFAULT '',
`level` tinyint(1) NOT NULL DEFAULT '0',
`isvalid` tinyint(1) NOT NULL DEFAULT '1',
`districttype` tinyint(1) NOT NULL DEFAULT '0',
`inserttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`areacode` varchar(10) NOT NULL DEFAULT '',
`isneedcheckmobile` tinyint(1) NOT NULL DEFAULT '0' COMMENT '该地区用户是否需要验证手机号',
PRIMARY KEY (`id`),
KEY `idx_districtname_path` (`districtname`,`path`),
KEY `idx_path` (`path`),
KEY `idx_parentid` (`parentid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
* W_DistrictInfo.sql
--
http://47.93.27.106/share/W_DistrictInfo.sql
* DistrctModel.go
package models
import (
"fmt"
"github.com/go-xorm/xorm"
"time"
)
type DistrictModel struct {
Id int64 `xorm:"not null pk autoincr INT(11)"`
Districtname string `json:"districtname" xorm:"varchar(50) not null 'districtname'"`
Districtcode string `json:"districtcode" xorm:"varchar(20) not null 'districtcode'"`
Parentid int64 `json:"parentid" xorm:"mediumint(8) not null 'parentid'"`
Path string `json:"path" xorm:"varchar(30) not null 'path'"`
Level int `json:"level" xorm:"tinyint(1) not null 'level'"`
Isvalid int `json:"isvalid" xorm:"tinyint(1) not null 'isvalid'"`
Districttype int `json:"districttype" xorm:"tinyint(1) not null 'districttype'"`
Inserttime time.Time `json:"inserttime" xorm:"timestamp not null 'inserttime'"`
Areacode string `json:"areacode" xorm:"varchar(10) not null 'areacode'"`
Isneedcheckmobile int `json:"isneedcheckmobile" xorm:"tinyint(1) not null 'isneedcheckmobile'"`
}
func (this *DistrictModel) TableName() string {
return "W_DistrictInfo"
}
func GetValidArea() ([]DistrictModel, error) {
var engine *xorm.Engine = nil
engine = DbDefault()
var list []DistrictModel
err := engine.Where("level", "3").Find(&list)
return list, err
}
func (this *DistrictModel) ToString() string {
return fmt.Sprintf("{id: %d, name:\"%s\", path:\"%s\", pid:%d}",
this.Id, this.Districtname, this.Path, this.Parentid)
}
func FilterAreaMap(list []map[string]interface{},
filterFunc func(map[string]interface{}) bool) []map[string]interface{} {
var n = len(list)
var sift []map[string]interface{}
for i := 0; i < n; i++ {
if filterFunc(list[i]) {
sift = append(sift, list[i])
}
}
return sift
}
func FilterAreaList(list []DistrictModel,
filterFunc func(DistrictModel) bool) []interface{} {
var sift []interface{}
var m map[string]interface{}
for _, e := range list {
if filterFunc(e) {
m = make(map[string]interface{})
m["id"] = e.Id
// m["pid"] = e.Parentid
m["items"] = make([]interface{}, 0)
m["name"] = e.Districtname
sift = append(sift, m)
}
}
return sift
}
func FilterCountry(list []DistrictModel,
filterFunc func(DistrictModel) bool) []string {
var sift []string
for _, e := range list {
if filterFunc(e) {
sift = append(sift, e.Districtname)
}
}
return sift
}
* District.go
package data
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"gitlab.easytech-main.com/mingzhanghui/ginplus/log"
"gitlab.easytech-main.com/webdev/ucenter/src/handlers"
"gitlab.easytech-main.com/webdev/ucenter/src/models"
"gitlab.easytech-main.com/webdev/ucenter/src/pkg/errno"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"time"
)
type District struct{}
const CACHE_PATH = "./conf/providers/district.json"
// 地区数据更新
func (this *District) V1(c *gin.Context) {
// 是否更新缓存 默认0不更新
var update = c.DefaultQuery("update", "0")
var list []interface{}
var err error
var cachePath string
cachePath, err = this.getLatestDistrictCachePath()
if err != nil {
handlers.SendResponse(c, errno.ErrOpenFile, err.Error())
return
}
// 没有json缓存文件, 或强制更新
if strings.Compare(cachePath, "") == 0 || strings.Compare(update, "1") == 0 {
list, err = this.getDistrictList()
if err != nil {
handlers.SendResponse(c, errno.ErrDatabase, err.Error())
return
}
go this.makeCache(list)
handlers.SendResponse(c, errno.OK, list)
return
}
// --- 以下 有缓存文件 ---
// TODO: 缓存文件过期
// 缓存文件存在没有过期, 直接读取
var content []byte
content, err = file_get_contents(cachePath)
if err != nil {
handlers.SendResponse(c, errno.ErrOpenFile, err.Error())
return
}
err = json.Unmarshal(content, &list)
if err != nil {
handlers.SendResponse(c, errno.ErrBind, err.Error())
return
}
handlers.SendResponse(c, errno.OK, list)
}
func (this *District) getLatestDistrictCachePath() (string, error) {
var providerDir = filepath.Dir(CACHE_PATH)
var files sort.StringSlice
var err error
var path string
files, err = filepath.Glob(providerDir + "/district*.json")
if len(files) < 1 {
return "", err
}
if err != nil {
return "", err
}
sort.Strings(files)
path = files[len(files)-1]
return path, nil
}
func (this *District) makeCache(list []interface{}) error {
var err error
var jsonStr []byte
jsonStr, err = json.Marshal(list)
if err != nil {
return err
}
var providerDir = filepath.Dir(CACHE_PATH)
var cachePath = fmt.Sprintf("%s/district_%s.json",
providerDir,
time.Now().Format("20060102"))
log.Info("District cache made: " + cachePath)
return file_put_contents(cachePath, jsonStr)
}
func (this *District) getDistrictList() ([]interface{}, error) {
var err error
var list []models.DistrictModel
var provinceList []interface{} // []models.DistrictModel
var cityList []interface{}
var countryList []string
var filterCity func(model models.DistrictModel) bool
var filterCountry func(model models.DistrictModel) bool
var m map[string]interface{}
var provinceMap map[string]interface{}
var cityMap map[string]interface{}
list, err = models.GetValidArea()
if err != nil {
return nil, err
}
provinceList = models.FilterAreaList(list, func(e models.DistrictModel) bool {
return e.Parentid == 0
})
for i, province := range provinceList {
filterCity = func(model models.DistrictModel) bool {
m = province.(map[string]interface{})
return model.Parentid == m["id"].(int64)
}
cityList = models.FilterAreaList(list, filterCity)
provinceMap = provinceList[i].(map[string]interface{})
provinceMap["items"] = cityList
for j, city := range cityList {
filterCountry = func(model models.DistrictModel) bool {
m = city.(map[string]interface{})
return model.Parentid == m["id"].(int64)
}
countryList = models.FilterCountry(list, filterCountry)
cityMap = cityList[j].(map[string]interface{})
cityMap["items"] = countryList
delete(cityMap, "id")
}
delete(provinceMap, "id")
// delete(provinceMap, "pid")
}
return provinceList, nil
}
func file_get_contents(filePath string) ([]byte, error) {
f, err := os.Open(filePath)
if err != nil {
return []byte{}, err
}
var ba []byte
ba, err = ioutil.ReadAll(f)
return ba, err
}
func file_put_contents(filePath string, content []byte) error {
return ioutil.WriteFile(filePath, content, 0644)
}
* router.go
// ...
// 地区列表
v1.GET("/district", new(data.District).V1)
// ...