トラック
/
Go
Go
/
演習
/
気象学
気象学

気象学

学習演習

はじめに

Stringerは、値の文字列フォーマットを定義するためのインターフェースです。

このインターフェースは、Stringという1つのメソッドだけで構成されています。

type Stringer interface {
    String() string
}

このインターフェースを実装したい型は、その型を人間にとってわかりやすく表した文字列を返すString()メソッドを持っている必要があります。 fmtパッケージ(ほかにも多くのパッケージ)は、値をフォーマットして出力するためにこのメソッドを探します。

例:距離

さまざまな単位で測った地理的な距離を扱うアプリケーションを開発しているとしましょう。 DistanceUnitとDistanceという型を次のように定義したとします。

type DistanceUnit int

const (
	Kilometer    DistanceUnit = 0
	Mile         DistanceUnit = 1
)

type Distance struct {
	number float64
	unit   DistanceUnit
}

上の例では、KilometerとMileはDistanceUnit型の定数です。

これらの型はStringメソッドを持っていないため、Stringerインターフェースを実装していません。 そのため、fmtの関数はGoの「デフォルトのフォーマット」でDistanceの値を出力します。

mileUnit := Mile
fmt.Sprint(mileUnit)
// => 1
// The result is '1' because that is the underlying value of the 'Mile' constant (see constant declarations above)

dist := Distance{number: 790.7, unit: Kilometer}
fmt.Sprint(dist)
// => {790.7 0}
// not a very useful output!

出力をよりわかりやすくするために、DistanceUnit型とDistance型それぞれにStringメソッドを追加して、Stringerインターフェースを実装します。

func (sc DistanceUnit) String() string {
	units := []string{"km", "mi"}
	return units[sc]
}

func (d Distance) String() string {
	return fmt.Sprintf("%v %v", d.number, d.unit)
}

fmtパッケージの関数は、Distanceの値をフォーマットするときにこれらのメソッドを呼び出します。

kmUnit := Kilometer
kmUnit.String()
// => km

mileUnit := Mile
mileUnit.String()
// => mi

dist := Distance{
	number: 790.7,
	unit: Kilometer,
}
dist.String()
// => 790.7 km

説明

チームは気象学のアプリケーションに取り組んでいます。 気象データを表すさまざまな型と定数を使ったAPIを定義しています。詳しくはmeteorology.goファイルを見てください。

ここでの課題は、すべての型に適切なStringメソッドを追加して、Stringerインターフェースを実装することです。

1. TemperatureUnit型にStringerインターフェースを実装する

話し合いの結果、チームは温度の単位をCelsiusまたはFahrenheitのいずれかにすることに決めました。 値は、以下の例のようにフォーマットする必要があります。

TemperatureUnit型にStringメソッドを追加して、Stringerインターフェースを実装させましょう。 このメソッドは、温度の単位がCelsiusなら"°C"、Fahrenheitなら"°F"という文字列を返す必要があります。

celsiusUnit := Celsius
fahrenheitUnit := Fahrenheit

celsiusUnit.String()
// => °C
fahrenheitUnit.String()
// => °F
fmt.Sprint(celsiusUnit)
// Output: °C

2. Temperature型にStringerインターフェースを実装する

Temperatureの値は、整数と温度の単位から構成されます。 以下の例のようにフォーマットする必要があります。

そのためには、Temperature型にStringメソッドを追加して、Stringerインターフェースを実装させましょう。 このメソッドは、温度の数値と温度の単位をスペースで区切った文字列を返すようにします:<temperature> <unit>:

celsiusTemp := Temperature{
    degree: 21,
    unit: Celsius,
}
celsiusTemp.String()
// => 21 °C
fmt.Sprint(celsiusTemp)
// Output: 21 °C

fahrenheitTemp := Temperature{
    degree: 75,
    unit: Fahrenheit,
}
fahrenheitTemp.String()
// => 75 °F
fmt.Sprint(fahrenheitTemp)
// Output: 75 °F

3. SpeedUnit型にStringerインターフェースを実装する

長い議論のすえ、チームは風速の単位をKmPerHourまたはMilesPerHourのいずれかにすることに決めました。 値は、以下の例のようにフォーマットする必要があります。

そのためには、SpeedUnit型にStringメソッドを追加して、Stringerインターフェースを実装させましょう。 このメソッドは、速度の単位がキロメートル毎時なら"km/h"、マイル毎時なら"mph"という文字列を返す必要があります。

mphUnit := MilesPerHour
mphUnit.String()
// => mph
fmt.Sprint(mphUnit)
// Output: mph

kmhUnit := KmPerHour
kmhUnit.String()
// => km/h
fmt.Sprint(kmhUnit)
// Output: km/h

4. SpeedにStringerインターフェースを実装する

風速の値は、整数と速度の単位から構成されます。 以下の例のようにフォーマットする必要があります。

そのためには、Speed型にStringメソッドを追加して、Stringerインターフェースを実装させましょう。 このメソッドは、速度の数値と速度の単位をスペースで区切った文字列を返すようにします:<speed> <unit>:

windSpeedNow := Speed{
    magnitude: 18,
    unit: KmPerHour,
}
windSpeedNow.String()
// => 18 km/h
fmt.Sprintf(windSpeedNow)
// Output: 18 km/h

windSpeedYesterday := Speed{
    magnitude: 22,
    unit: MilesPerHour,
}
windSpeedYesterday.String()
// => 22 mph
fmt.Sprint(windSpeedYesterday)
// Output: 22 mph

5. MeteorologyData型にStringerインターフェースを実装する

気象データは、場所、気温、風向、風速、湿度を指定します。 以下の例のようにフォーマットする必要があります。

そのためには、MeteorologyData型にStringメソッドを追加して、Stringerインターフェースを実装させましょう。 このメソッドは、気象データを次の形式で返すようにします:

<location>: <temperature>, Wind <wind_direction> at <wind_speed>, <humidity>% Humidity
sfData := MeteorologyData{
    location: "San Francisco",
    temperature: Temperature{
        degree: 57,
        unit: Fahrenheit
    },
    windDirection: "NW",
    windSpeed: Speed{
        magnitude: 19,
        unit: MilesPerHour
    },
    humidity: 60
}

sfData.String()
// => San Francisco: 57 °F, Wind NW at 19 mph, 60% Humidity
fmt.Sprint(sfData)
// Output: San Francisco: 57 °F, Wind NW at 19 mph, 60% Humidity
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Go Exercism

気象学を始める準備はできましたか?

Exercismに登録すれば、34個のコンセプト166個の演習、そして本物の人間によるメンタリングとともに、Goを学んでマスターできます。すべて無料です。