用 net/http 发起带 query 参数的 get 请求需:1. 用 url.values 安全构造查询参数并转义中文;2. 从环境变量读取 api key;3. 正确使用 json tag 解析嵌套响应;4. 用 flag 解析命令行参数;5. 设置 http.client 超时避免假死。

怎么用 net/http 发起带 query 参数的 GET 请求
天气 API 大多靠 URL 查询参数传城市名或经纬度,比如 https://api.openweathermap.org/data/2.5/weather?q=Beijing&appid=xxx。别手拼 URL 字符串——容易漏转义、丢 & 或 =。net/url 的 url.Values 是标准解法。
- 先用
url.Parse解析基础地址,再用url.Values.Set填参数,最后用u.RawQuery = params.Encode()组装 - 中文城市名(如 “上海”)必须走
url.QueryEscape,否则服务端收不到或返回 400 - 别把
appid拼在 URL 里硬编码,读环境变量更安全:os.Getenv("WEATHER_API_KEY")
解析 JSON 响应时 struct 字段 tag 写不对就全为零值
OpenWeatherMap 返回的 JSON 字段名是 main、wind 这类小写加下划线的,Go struct 默认只匹配首字母大写的导出字段,且忽略下划线。不写 json: tag,json.Unmarshal 就不会把数据塞进去,所有字段都是零值。
-
Temp字段得写成Temp float64 `json:"temp"`,不是"Temp"或"temperature" - 嵌套对象如
main对应的 struct 要单独定义,tag 里写main,不能省略或改成Main - 可选字段(比如某些城市没
rain)用指针类型 +omitempty:Rain *struct{ OneHour float64 } `json:"rain,omitempty"`
命令行参数解析用 flag 就够了,别上 cobra
这个工具只需要一个 -city 或 -lat/-lon,没子命令、没交互、不生成 help 文档——cobra 是过度设计,还引入隐式全局状态和额外编译体积。
- 用
flag.StringVar(&city, "city", "", "城市名,如 shanghai"),然后flag.Parse() - 检查是否至少传了一个参数:
if city == "" && (lat == 0 || lon == 0),直接log.Fatal("需指定 -city 或 -lat/-lon") - 别忘了调
flag.Usage = func(){...}自定义提示,否则默认输出一堆-v-h等无关项
HTTP 超时没设,请求卡住就整个程序挂住
默认 http.DefaultClient 没超时,遇到网络抖动或 API 无响应,client.Do() 会一直等下去,命令行工具就“假死”。这不是 bug,是没配。
立即学习“go语言免费学习笔记(深入)”;
- 必须显式创建
http.Client并设Timeout:&http.Client{Timeout: 10 * time.Second} - 别只设
Timeout,还要考虑 DNS 解析慢:用http.Transport配.DialContext和ResponseHeaderTimeout - 错误处理别只看
err != nil,要区分url.Error中的Timeout()结果,方便提示用户“请求超时,请重试”
天气 API 的响应结构松散、字段可选、单位不统一(开尔文 vs 摄氏)、坐标精度要求高——这些细节不提前对齐,跑通第一版后很快就会在解析温度或定位上海时掉坑里。










