GoでのAPIを引っ張ってくるやり方

# はじめに
Slackbotでの天気予報をお知らせするbotを作成しました。以下、コード。

**[天気予報Bot](https://github.com/shxun6934/Weather_Bot)**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179470/19b2123b-f469-27f8-cfd3-bcc9026f5fa7.png)


このbot作成時につまづいた、GoでのAPIをここに記します。
※botに関しての記事ではないので、注意。

## API
今回使用した天気予報を持ってくるAPIは、[OpenWeatherAPI](https://openweathermap.org/api)です。

また、Slackbotを作成したため、もしよければ[Slackapi](https://api.slack.com/)を使用してbotを作成してください。

登録方法は、以下のサイト参考。
[無料天気予報APIのOpenWeatherMapを使ってみる](https://qiita.com/nownabe/items/aeac1ce0977be963a740)

[Slack Botの種類と大まかな作り方](https://qiita.com/namutaka/items/233a83100c94af033575)

## API Get
GoogleChromeのアプリ等で実際に、OpenWeatherMapのAPIを叩いてみます。
以下のURLを叩けば、JSONで返ってきます。

`http://api.openweathermap.org/data/2.5/weather?lat=緯度&lon=経度&appid=apikey`

例：石川県野々市市

```json
{
    "coord": {
        "lon": 136.63,
        "lat": 36.53
    },
    "weather": [
        {
            "id": 801,
            "main": "Clouds",
            "description": "few clouds",
            "icon": "02n"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 278.32,
        "feels_like": 275.8,
        "temp_min": 277.59,
        "temp_max": 279.15,
        "pressure": 1023,
        "humidity": 75
    },
    "visibility": 10000,
    "wind": {
        "speed": 1
    },
    "clouds": {
        "all": 20
    },
    "dt": 1576494007,
    "sys": {
        "type": 1,
        "id": 8017,
        "country": "JP",
        "sunrise": 1576447105,
        "sunset": 1576481950
    },
    "timezone": 32400,
    "id": 1854979,
    "name": "Nonoichi",
    "cod": 200
}
```

このJSONをGo言語で扱うには、構造体をしようしなくてはいけません。
JSONをGoの構造体で表すと以下のようになります。

[JSON-to-Go](https://mholt.github.io/json-to-go/)を使用すれば一発です。

```go
type WeatherResult struct {
	Coord struct {
		Lon float64 `json:"lon"`
		Lat float64 `json:"lat"`
	} `json:"coord"`
	Weather []struct {
		ID          int    `json:"id"`
		Main        string `json:"main"`
		Description string `json:"description"`
		Icon        string `json:"icon"`
	} `json:"weather"`
	Base string `json:"base"`
	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"`
	Visibility int `json:"visibility"`
	Wind       struct {
		Speed int `json:"speed"`
	} `json:"wind"`
	Clouds struct {
		All int `json:"all"`
	} `json:"clouds"`
	Dt  int `json:"dt"`
	Sys struct {
		Type    int    `json:"type"`
		ID      int    `json:"id"`
		Country string `json:"country"`
		Sunrise int    `json:"sunrise"`
		Sunset  int    `json:"sunset"`
	} `json:"sys"`
	Timezone int    `json:"timezone"`
	ID       int    `json:"id"`
	Name     string `json:"name"`
	Cod      json.Number    `json:"cod"`
}
```

botを作成する際には、必要なものだけでも大丈夫です。（例えば、Weatherとか）
準備ができたので、`main.go`で実際に持ってきましょう。



```go:main.go
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
)

// 中略 ここに先ほどの構造体を入れる。

func main() {
	result := GetWeather()
        
	fmt.Println(result)
}

// APIを叩く関数
func GetWeather() string {
	values := url.Values{}
	baseUrl := "http://api.openweathermap.org/data/2.5/weather?"
        
    // query
	values.Add("appid", "APIKEY")    // OpenWeatherのAPIKey
	values.Add("lat", "36.5286")     // 緯度（石川県野々市市）
	values.Add("lon", "136.6283")    // 経度(石川県野々市市)

	weather := ParseJson(baseUrl + values.Encode())
	return weather
}

// ここでパースします。
func ParseJson(url string) string {
	weather := ""

	response, err := http.Get(url)
	if err != nil {   // エラーハンドリング
		log.Fatalf("Connection Error: %v", err)
		return "取得できませんでした"
	}

   // 遅延
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Fatalf("Connection Error: %v", err)
		return "取得できませんでした"
	}

	jsonBytes := ([]byte)(body)
	data := new(WeatherResult)
	if err := json.Unmarshal(jsonBytes, data); err != nil {
		log.Fatalf("Connection Error: %v", err)
	}

	if data.Weather != nil {
		weather = data.Weather[0].Main
	}
	return weather
}
```

やっていることは、簡単。

`GetAPI`は、ベースとなるURLを変数に、必要なqueryを構造体に保管します。それらを組み合わせて
`ParseJson`に渡します。

`http`パッケージでのGetメソッドでGETし、持ってきたBodyを`ioutil`パッケージで読み込みます。
それをbyte型で格納し、データを表示します。

ターミナルで、`go run main.go`を走らせると、設定した都市の気候が表示されます。

これで、APIを持ってくることができました。

# 終わりに
他の言語は、ライブラリーや標準で実装できるのに、goはできないのがかなり不便ですね。

多分、あると思いますが、データの流れがわかるので自分で書くのもありかな。