轨道
/
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类型的常量。

这些类型没有实现Stringer接口,因为它们缺少String方法。因此,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类型实现Stringer接口,给每个类型添加一个String方法:

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)
}

在格式化Distance值时,fmt包中的函数会调用这些方法:

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接口。 如果温度单位是摄氏度,该方法必须返回字符串"°C";如果温度单位是华氏度,则必须返回字符串"°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,全部免费。