通过cobra开发天气查询小工具

简介: 通过cobra开发天气查询小工具

介绍 cobra


cobra 是一个 Golang 包,它提供了简单的接口来创建命令行程序。同时它也是一个应用程序,用来生成应用框架,从而开发以 cobra 为基础的应用。在 GitHub 上,有更多关于 cobra 的介绍。网上也有关于此项目的一些文章,只是 10 篇文章到最后可能 9 篇都是重复的,仅此而已。


说明


为了不增加文章的重复率,也为了达到学习的效果,通过此项目来实现一些小功能。最终的效果是通过命令行输入城市名或者城市码获取当前城市的温度情况。


1668568346283.jpg


实现


入口文件的目的只有一个初始化 cobra

func main() {
    _ = cmd.Execute()
}
package cmd
import (
    "github.com/spf13/cobra"
)
var (
    weatherCmd = &cobra.Command{
        Use: "weather",
    }
)
func Execute() error {
    return weatherCmd.Execute()
}

然后在其他的两个文件中,分别定义了此 cmd 的两个子命令。分别表示通过城市名称 NameCmd 和通过城市码 CodeCmd 来查询天气情况。


通过城市名称


package cmd
import (
    "errors"
    "fmt"
    "os"
    "github.com/spf13/cobra"
    "github.com/wuqinqiang/go-weather/server"
    "github.com/wuqinqiang/go-weather/tools"
)
func init() {
    NameCmd.PersistentFlags().StringP("name", "n", "", "input city name")
    weatherCmd.AddCommand(NameCmd)
}
var NameCmd = &cobra.Command{
    Use:   "name",
    Short: "check city weather by city name",
    Args: func(cmd *cobra.Command, args []string) error {
        name, err := cmd.Flags().GetString("name")
        if err != nil {
            return errors.New("please input city name")
        }
        if len(name) == 0 {
            return errors.New("请携带参数-n 或者 --name")
        }
        return nil
    },
    Run: func(cmd *cobra.Command, args []string) {
        name, _ := cmd.Flags().GetString("name")
        code := tools.CityMap[name]
        if code == 0 {
            fmt.Println("这个城市我不想查")
            os.Exit(1)
        }
        info, err := server.GetWeather(code)
        if err != nil {
            fmt.Println(err.Error())
            os.Exit(1)
        }
        fmt.Println("查询的天气是:", info)
    },
}

通过城市码


package cmd
import (
    "errors"
    "fmt"
    "os"
    "github.com/spf13/cobra"
    "github.com/wuqinqiang/go-weather/server"
)
func init() {
    codeCmd.PersistentFlags().IntP("code", "c", 0, "城市码必须是6位的整数")
    weatherCmd.AddCommand(codeCmd)
}
var codeCmd = &cobra.Command{
    Use:   "code",
    Short: "check city weather by city code",
    Args: func(cmd *cobra.Command, args []string) error {
        code, err := cmd.Flags().GetInt("code")
        if err != nil {
            return errors.New("请输入城市码")
        }
        if code == 0 {
            return errors.New("请携带参数-c 或者 --code")
        }
        return nil
    },
    Run: func(cmd *cobra.Command, args []string) {
        code, _ := cmd.Flags().GetInt("code")
        info, err := server.GetWeather(code)
        if err != nil {
            fmt.Println(err.Error())
            os.Exit(1)
        }
        fmt.Println("查询的天气是:", info)
    },
}

cobra.Command 里面的 Args 主要做一些参数验证,Run 就是实际工作功能,也是核心部分,大部分命令只会实现这一点。


至于获取天气,你可以看到 server.GetWeather 其实就是对接高德的 api 接口,发送了一个 http 请求罢了。

const (
     Key = "xx" //高德key
    Uri = "https://restapi.amap.com/v3/weather/weatherInfo" //api地址
)
//响应天气数据
func GetWeather(code int) (map[string]interface{}, error) {
    info, err := GetWeatherRequest(code)
    if err != nil {
        return nil, err
    }
    infoMap := make(map[string]interface{})
    infoMap["城市:"] = info.Lives[0].City
    infoMap["天气现象:"] = info.Lives[0].Weather
    infoMap["实时气温:"] = info.Lives[0].Temperature
    infoMap["数据发布:"] = info.Lives[0].Reporttime
    return infoMap, nil
}
//请求接口
func GetWeatherRequest(code int) (entity.ResponseInfo, error) {
    info := entity.ResponseInfo{}
    client := &http.Client{Timeout: 2 * time.Second}
    url := fmt.Sprintf(Uri+"?key=%s&city=%d", Key, code)
    resp, err := client.Get(url)
    if err != nil {
        fmt.Println("查询错误:", err)
        return info, errors.New("查询失败")
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read body err:", err)
        return info, errors.New("查询失败")
    }
    if err := json.Unmarshal(body, &info); err != nil {
        fmt.Println("unmarshal response err:", err)
        return info, errors.New("查询失败,请输入正确的城市码")
    }
    if info.Status != "1" {
        return info, errors.New("api 密钥key错误,请检查")
    }
    return info, nil
}

这一块没咋么设计,使得获取天气的信息高度依赖于高德的接口,假设我们现在用其他的方式来获取天气,那么就需要大调整当前的代码。这一块理应抽象化。

最后,整个项目的结构如下:


1668568411752.jpg


相关文章
|
8月前
|
数据采集 数据挖掘 Go
踏入网页抓取的旅程:使用 grequests 构建 Go 视频下载器
使用 Go 和 grequests 构建 Bilibili 视频下载器,结合爬虫代理 IP 提高下载稳定性与速度。通过获取视频信息、构建下载链接、设置代理IP及异步请求,实现视频的本地保存。代码示例展示了如何运用 grequests 请求选项配置代理及处理请求。
108 3
踏入网页抓取的旅程:使用 grequests 构建 Go 视频下载器
|
小程序 JavaScript API
【Pyqt实战】全国天气查询小程序(含UI界面,python代码)
【Pyqt实战】全国天气查询小程序(含UI界面,python代码)
|
JavaScript 关系型数据库 测试技术
接口文档管理神器RAP2安装和部署
一 RAP2 RAP2是在RAP1基础上重做的新项目,它包含两个组件(对应两个Github Repository)。 rap2-delos: 后端数据API服务器,基于Koa + MySQLlink rap2-dolores: 前端静态资源,基于React link 什么是RAP? rap是一款API 文档管理工具,在 RAP 中,可以定义接口的 URL、请求 & 响应细节格式等等。
13100 0
|
4月前
|
前端开发 JavaScript 开发工具
web应用开发工具
【9月更文挑战第1天】web应用开发工具
81 3
|
5月前
|
测试技术 API 开发者
Python 魔法:打造你的第一个天气查询小工具自动化测试框架的构建与实践
【8月更文挑战第31天】在这篇文章中,我们将一起踏上编程的奇妙旅程。想象一下,只需几行代码,就能让计算机告诉你明天是否要带伞。是的,你没有听错,我们将用Python这把钥匙,解锁天气预报的秘密。不论你是编程新手还是想拓展技能的老手,这篇文章都会为你带来新的视角和灵感。所以,拿起你的键盘,让我们一起创造属于自己的天气小工具吧!
|
5月前
|
搜索推荐 API 数据处理
Python魔法:打造个性化天气查询工具
【8月更文挑战第31天】 在这篇文章中,我们将一起探索如何用Python构建一个个性化的天气查询工具。不同于传统的技术文章,我们将通过一个简单的故事引入主题,让读者感受到编程的乐趣和实用性。文章将介绍如何使用API获取数据,处理这些数据,并以用户友好的方式展示信息。无论你是编程新手还是想扩展你的项目库,这篇文章都会给你提供有价值的见解和代码示例。
|
5月前
|
JSON IDE API
探索Python编程:打造你的第一个天气查询工具
【8月更文挑战第30天】在这篇文章中,我们将一起踏上Python编程的奇妙旅程,从零基础开始,逐步构建出属于自己的天气查询工具。文章将引导你了解Python语言的魅力,通过实际的项目操作,让你体验到编程的乐趣和成就感。无论你是编程新手还是希望扩展技能的老手,这篇文章都将为你提供宝贵的经验和知识。让我们一起探索代码的世界,解锁新技能,让技术改变生活!
|
JSON 数据格式 Python
使用python开发天气预报程序(带gui)
使用python开发天气预报程序(带gui)
202 0
|
数据采集 小程序 程序员
使用Python制作天气查询系统
使用Python制作天气查询系统
使用Python制作天气查询系统
|
JSON 数据可视化 JavaScript
颜值爆表!推荐两款JSON可视化工具,配合Swagger使用真香
经常使用Swagger的小伙伴应该有所体会,Swagger对于JSON的支持真的很不友好!最近发现了两款颜值很不错的JSON可视化工具,可以优雅地展示JSON数据从而提高开发效率,推荐给大家! 聊聊Swagger 我们先来聊聊Swagger对JSON支持有哪些不友好的地方,我们为什么需要JSON可视化工具! 当我们使用Swagger提交POST请求,输入JSON请求参数时,它既不支持JSON格式校验,也不支持格式化,用起来很不方便;