學習軌道
/
Go
Go
/
練習
/
氣象學
氣象學

氣象學

學習練習

簡介

Stringer 是一個介面,用來定義值的字串格式。

這個介面只包含一個 String 方法:

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 型別加上 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,全部免費。