问题:

提供天气信息的网站有很多,每家的数据及格式都不同,为了适配各种不同的天气接口,写了如下程序。

代码如下:

package main

import (
"encoding/json"
"errors"
"fmt"
"regexp"
"strconv"
"strings"
) var s string = `
{
"error": ,
"status": "success",
"date": "2015-03-26",
"results": [
{
"test": [
[
"fuck",
"shit"
],
{
"ao": "xxx"
},
"vfe"
],
"currentCity": "郑州",
"pm25": "",
"index": [
{
"title": "穿衣",
"zs": "较冷",
"tipt": "穿衣指数",
"des": "建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。"
},
{
"title": "洗车",
"zs": "不宜",
"tipt": "洗车指数",
"des": "不宜洗车,未来24小时内有雨,如果在此期间洗车,雨水和路上的泥水可能会再次弄脏您的爱车。"
},
{
"title": "旅游",
"zs": "适宜",
"tipt": "旅游指数",
"des": "温度适宜,又有较弱降水和微风作伴,会给您的旅行带来意想不到的景象,适宜旅游,可不要错过机会呦!"
},
{
"title": "感冒",
"zs": "少发",
"tipt": "感冒指数",
"des": "各项气象条件适宜,无明显降温过程,发生感冒机率较低。"
},
{
"title": "运动",
"zs": "较不宜",
"tipt": "运动指数",
"des": "有降水,推荐您在室内进行健身休闲运动;若坚持户外运动,须注意保暖并携带雨具。"
},
{
"title": "紫外线强度",
"zs": "最弱",
"tipt": "紫外线强度指数",
"des": "属弱紫外线辐射天气,无需特别防护。若长期在户外,建议涂擦SPF在8-12之间的防晒护肤品。"
}
],
"weather_data": [
{
"date": "周四 03月26日 (实时:12℃)",
"dayPictureUrl": "http://api.map.baidu.com/images/weather/day/zhenyu.png",
"nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png",
"weather": "阵雨转多云",
"wind": "微风",
"temperature": "12 ~ 4℃"
},
{
"date": "周五",
"dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png",
"nightPictureUrl": "http://api.map.baidu.com/images/weather/night/qing.png",
"weather": "晴",
"wind": "微风",
"temperature": "16 ~ 8℃"
},
{
"date": "周六",
"dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png",
"nightPictureUrl": "http://api.map.baidu.com/images/weather/night/duoyun.png",
"weather": "晴转多云",
"wind": "微风",
"temperature": "22 ~ 9℃"
},
{
"date": "周日",
"dayPictureUrl": "http://api.map.baidu.com/images/weather/day/qing.png",
"nightPictureUrl": "http://api.map.baidu.com/images/weather/night/qing.png",
"weather": "晴",
"wind": "微风",
"temperature": "25 ~ 11℃"
}
]
}
]
}
` // 天气
type Weather struct {
Error_Code string `json:"error_code"` //错误码 0没有错误
Status string `json:"status"` // 状态描述, success 成功
Result Result `json:"result"` // 天气状况
} // 天气结果
type Result struct {
Now Real
LivingIndex []Indicate `json:"living_index"` //生活指数
Future []ForeCast `json:"future"` //未来几天的预报,包括当天
} // 实时报告
type Real struct {
City string `json:"city"` // 城市
Temperature string `json:"temperature"` // 当前温度
WindDirection string `json:"wind_direction"` // 风向
WindStrength string `json:"wind_strength"` // 风强度
Humidity string `json:"humidity"` // 湿度
PM25 string `json:"pm25"` // PM2.5
} // 预报
type ForeCast struct {
Temperature string `json:"temperature"` // 温度范围
Weather string `json:"weather"` // 天气 (晴,多云,阴转多云)
Wind string `json:"wind"` // 风向和强度
Week string `json:"week"` // 星期几
Date string `json:"date"` // 日期
} type Indicate struct {
Title string `json:"titile"` // 指数标题
Status string `json:"status"` //指数状态 (适宜,不宜)
Description string `json:"desc"` //描述信息
} func NewWeather() *Weather {
return NewWeatherWithNum(, )
} func NewWeatherWithNum(livingIndexNum, forecastNum int) *Weather {
w := &Weather{}
w.Result.LivingIndex = make([]Indicate, livingIndexNum)
w.Result.Future = make([]ForeCast, forecastNum)
return w
} type ElementExtractor struct {
Err error
m map[string]interface{}
r *regexp.Regexp
} func NewElementExtractor(jsonString string) *ElementExtractor {
ee := &ElementExtractor{r: regexp.MustCompile(`(.*)\[(\d+)\]+`)}
ee.Err = json.Unmarshal([]byte(jsonString), &ee.m)
return ee
} func (ee *ElementExtractor) ExtractElementByPattern(patten string) (string, error) {
if ee.Err != nil {
return "", ee.Err
} var mm map[string]interface{} = ee.m
var sa []interface{} patten = strings.Replace(patten, "][", "].[", -) for _, k := range strings.Split(patten, ".") {
ki := ee.r.FindStringSubmatch(k)
if len(ki) == {
j, _ := strconv.Atoi(ki[])
if ki[] != "" {
sa = mm[ki[]].([]interface{})
} switch s := sa[j].(type) {
case string:
return s, nil
case map[string]interface{}:
mm = s
case []interface{}:
sa = sa[j].([]interface{})
default:
return fmt.Sprintf("%v", s), nil
}
} else {
switch s := mm[k].(type) {
case string:
return s, nil
case map[string]interface{}:
mm = s
default:
return fmt.Sprintf("%v", s), nil
}
}
} ee.Err = errors.New("Pattern Error: " + patten)
return "", ee.Err
} func main() {
ee := NewElementExtractor(s)
w := NewWeather() w.Status, _ = ee.ExtractElementByPattern("status")
w.Error_Code, _ = ee.ExtractElementByPattern("error")
w.Result.Now.City, _ = ee.ExtractElementByPattern("results[0].currentCity")
w.Result.Now.PM25, _ = ee.ExtractElementByPattern("results[0].pm25")
w.Result.Future[].Date, _ = ee.ExtractElementByPattern("results[0].weather_data[2].date")
w.Result.LivingIndex[].Title, _ = ee.ExtractElementByPattern("results[0].index[0].title")
w.Result.Future[].Temperature, _ = ee.ExtractElementByPattern("results[0].weather_data[2].temperature")
w.Result.Now.PM25, _ = ee.ExtractElementByPattern("results[0].test[0][1]")
w.Result.Now.WindDirection, _ = ee.ExtractElementByPattern("results[0].test[1].ao")
w.Result.Now.WindStrength, _ = ee.ExtractElementByPattern("results[0].test[2]") if ee.Err != nil {
fmt.Println(ee.Err)
} else {
fmt.Println(w)
}
}

运行结果:

&{0 success {{郑州  xxx vfe  shit} [{穿衣  } {  } {  } {  } {  } {  }] [{    } {    } {22 ~ 9℃    周六} {    }]}}

[笔记]Go语言实现同一结构体适配多种消息源的更多相关文章

  1. C语言中的结构体,结构体数组

    C语言中的结构体是一个小难点,下面我们详细来讲一下:至于什么是结构体,结构体为什么会产生,我就不说了,原因很简单,但是要注意到是结构体也是连续存储的,但要注意的是结构体里面类型各异,所以必然会产生内存 ...

  2. Go语言基础之结构体

    Go语言基础之结构体 Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. 类型别名和自定义类型 自定义类型 在G ...

  3. 4-17疑难点 c语言之【结构体对齐】

    今天学习了结构体这一章节,了解到了结构体在分配内存的时候采取的是对齐的方式 例如: #include<stdio.h> struct test1 { int a; char b; shor ...

  4. C语言第九讲,结构体

    C语言第九讲,结构体 一丶结构体的定义 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{ 结构体所包含的变量或数组 }; 结构体是一种 ...

  5. C 语言实例 - 使用结构体(struct)

    C 语言实例 - 使用结构体(struct) C 语言实例 C 语言实例 使用结构体(struct)存储学生信息. 实例 #include <stdio.h> struct student ...

  6. Verilog缺少一个复合数据类型,如C语言中的结构体

    https://mp.weixin.qq.com/s/_9UsgUQv-MfLe8nS938cfQ Verilog中的数据类型(Data Type)是分散的,缺少一个复合数据类型:把多个wire, r ...

  7. GO学习-(13) Go语言基础之结构体

    Go语言基础之结构体 Go语言中没有"类"的概念,也不支持"类"的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. ...

  8. 【学习笔记】【C语言】指向结构体的指针

    1.指向结构体的指针的定义 struct Student *p;  2.利用指针访问结构体的成员 1> (*p).成员名称 2> p->成员名称 3.代码 #include < ...

  9. C语言中的结构体

    用户自己建立自己的结构体类型 1.  定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...

随机推荐

  1. MapReduce实战(一)自定义类型

    需求: 处理以下流量数据,第1列是手机号,第7列是上行流量,第8列是下行流量.将手机号一样的用户进行合并,上行流量汇总,下行流量也汇总,并相加求得总流量. 1363157985066 13726230 ...

  2. Java 设计模式01 - 简单工厂模式

    先要学习设计模式之前的先看看一些基础 UML类图简单说明 可以先看看我的这篇博客: UML类图简单说明,学习编程思路的必会技能 接下来才是重点,开始我们的旅程吧. 一.UML类图展示 我们要用简单工厂 ...

  3. 在使用add()方法添加组件到容器时,必须指定将其放置在哪个区域中

    BorderLayout是Window.Frame和Dialog的默认布局管理器,其将容器分成North.South.East.West和Center 5个区域,每个区域只能放置一个组件. 在使用ad ...

  4. 要生成一个窗口,通常使用Window的子类Frame类进行实例化

    要生成一个窗口,通常使用Window的子类Frame类进行实例化,而不是直接使用Window 类,框架的外观就像平常Windows系统下的窗口,有标题.边框. 菜单 和大小等. setSize()方法 ...

  5. 【vijos】1757 逆序对(dp)

    https://vijos.org/p/1757 有时候自己sb真的是不好说... 我竟然想了半天都没想到这个转移. 我是有多傻.... 我们设f[i][j]表示1~i的排列且逆序对恰好是j的方案数. ...

  6. poj 3249(bfs+dp或者记忆化搜索)

    题目链接:http://poj.org/problem?id=3249 思路:dp[i]表示到点i的最大收益,初始化为-inf,然后从入度为0点开始bfs就可以了,一开始一直TLE,然后优化了好久才4 ...

  7. PHP和JS判断手机还是电脑访问

    当用户使用手机等移动终端访问网站时,我们可以通过程序检测用户终端类型,如果是手机用户,则引导用户访问适配手机屏幕的移动站点.本文将介绍分别使用PHP和JAVASCRIPT代码判断用户终端类型. PHP ...

  8. java-web 过滤器 &amp; 监听器 &amp; 拦截器

    Tomcat 的容器分为四个等级.真正管理 Servlet 的容器是 Context 容器,一个 Context 对应一个 Web 工程.在 Tomcat 的配置文件里能够非常easy发现这一点.例如 ...

  9. 7.解决谷歌的SDK更新失败问题。

    问题: 近期谷歌被墙之后,更新SDK老是失败.提示Download interrupted: Connection to https://dl-ssl.google.com refused(下载中断, ...

  10. django用户认证系统——重置密码7

    当用户不小心忘记了密码时,网站需要提供让用户找回账户密码的功能.在示例项目中,我们将发送一封含有重置用户密码链接的邮件到用户注册时的邮箱,用户点击收到的链接就可以重置他的密码,下面是具体做法. 发送邮 ...