使用Golang和OpenWeather API构建天气应用
使用Golang和OpenWeather API构建天气应用 我最近撰写了一份详细的指南,介绍如何使用 OpenWeather API 在 Go 语言中构建一个天气应用程序。内容涵盖了进行 API 调用、解析 JSON 数据以及展示结果。如果你感兴趣,这里是链接:使用 OpenWeather API 在 Go 中构建天气应用程序。我很想听听你的反馈!
2 回复
这非常酷且实用。感谢您的付出!
更多关于使用Golang和OpenWeather API构建天气应用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
关于使用Golang和OpenWeather API构建天气应用的评论
看了你的教程,实现得很完整!这里我补充几个实际开发中可能会用到的优化点和技术细节:
1. 使用结构体标签处理JSON字段命名差异
OpenWeather API返回的字段有时使用蛇形命名法,而Go习惯使用驼峰式。可以通过结构体标签优雅处理:
type WeatherResponse struct {
Coord struct {
Lon float64 `json:"lon"`
Lat float64 `json:"lat"`
} `json:"coord"`
Main struct {
Temp float64 `json:"temp"`
FeelsLike float64 `json:"feels_like"`
TempMin float64 `json:"temp_min"`
TempMax float64 `json:"temp_max"`
Pressure int `json:"pressure"`
Humidity int `json:"humidity"`
} `json:"main"`
Name string `json:"name"`
}
2. 添加请求超时和重试机制
生产环境中需要更健壮的HTTP客户端:
func fetchWeatherData(apiKey, city string) (*WeatherResponse, error) {
client := &http.Client{
Timeout: 10 * time.Second,
}
url := fmt.Sprintf(
"https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric",
city, apiKey,
)
// 重试逻辑
var resp *http.Response
var err error
for i := 0; i < 3; i++ {
resp, err = client.Get(url)
if err == nil && resp.StatusCode == 200 {
break
}
time.Sleep(time.Duration(i+1) * time.Second) // 指数退避
}
if err != nil {
return nil, fmt.Errorf("请求失败: %v", err)
}
defer resp.Body.Close()
// 解析响应...
}
3. 使用context控制请求生命周期
特别是需要处理用户取消请求的场景:
func fetchWeatherWithContext(ctx context.Context, apiKey, city string) (*WeatherResponse, error) {
req, err := http.NewRequestWithContext(
ctx,
"GET",
fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s", city, apiKey),
nil,
)
if err != nil {
return nil, err
}
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// 解析响应...
}
4. 添加响应缓存减少API调用
对于天气数据这种变化不频繁的内容,可以添加本地缓存:
type WeatherCache struct {
data map[string]WeatherCacheEntry
mu sync.RWMutex
}
type WeatherCacheEntry struct {
data *WeatherResponse
timestamp time.Time
}
func (c *WeatherCache) Get(city string) (*WeatherResponse, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
entry, exists := c.data[city]
if !exists {
return nil, false
}
// 缓存10分钟
if time.Since(entry.timestamp) > 10*time.Minute {
return nil, false
}
return entry.data, true
}
5. 错误处理的完整示例
更全面的错误处理可以提升用户体验:
func getWeather(apiKey, city string) error {
weather, err := fetchWeatherData(apiKey, city)
if err != nil {
if strings.Contains(err.Error(), "timeout") {
return fmt.Errorf("请求超时,请检查网络连接")
}
if strings.Contains(err.Error(), "404") {
return fmt.Errorf("城市 '%s' 未找到", city)
}
if strings.Contains(err.Error(), "401") {
return fmt.Errorf("API密钥无效")
}
return fmt.Errorf("获取天气数据失败: %v", err)
}
// 处理数据...
return nil
}
你的教程涵盖了核心流程,这些补充内容可以帮助开发者构建更健壮的生产级应用。特别是错误处理和缓存机制,在实际部署中非常重要。

