Percursos
/
Go
Go
/
Exercícios
/
Meteorologia
Meteorologia

Meteorologia

Exercício de aprendizagem

Introdução

Stringer é uma interface para definir o formato de string dos valores.

A interface é composta por um único método String:

type Stringer interface {
    String() string
}

Os tipos que querem implementar esta interface têm de ter um método String() que devolva uma representação do tipo em string fácil de ler para uma pessoa. O pacote fmt (e muitos outros) procura este método para formatar e imprimir valores.

Exemplo: Distâncias

Imagina que estás a trabalhar numa aplicação que lida com distâncias geográficas medidas em unidades diferentes. Definimos os tipos DistanceUnit e Distance da seguinte forma:

type DistanceUnit int

const (
	Kilometer    DistanceUnit = 0
	Mile         DistanceUnit = 1
)

type Distance struct {
	number float64
	unit   DistanceUnit
}

No exemplo acima, Kilometer e Mile são constantes do tipo DistanceUnit.

Estes tipos não implementam a interface Stringer, porque não têm o método String. Por isso, as funções de fmt imprimem os valores de Distance usando o "formato predefinido" do Go:

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!

Para tornar o resultado mais informativo, implementamos a interface Stringer para os tipos DistanceUnit e Distance, acrescentando um método String a cada um deles:

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

As funções do pacote fmt chamam estes métodos ao formatar valores de Distance:

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

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

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

Instruções

A tua equipa está a trabalhar numa aplicação de meteorologia. Definiram uma API com vários tipos e constantes que representam dados meteorológicos; vê o ficheiro meteorology.go.

A tua tarefa é adicionar métodos String adequados a todos os tipos, para que implementem a interface Stringer.

1. Implementa a interface Stringer para o tipo TemperatureUnit

Depois de alguma discussão, a equipa concordou que a unidade de temperatura será Celsius ou Fahrenheit. Os valores devem ser formatados como mostram os exemplos abaixo.

Faz com que o tipo TemperatureUnit implemente a interface Stringer, adicionando-lhe um método String. Este método deve devolver a string "°C" se a unidade de temperatura for Celsius, ou "°F" se a unidade de temperatura for Fahrenheit.

celsiusUnit := Celsius
fahrenheitUnit := Fahrenheit

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

2. Implementa a interface Stringer para o tipo Temperature

Os valores de temperatura são compostos por um número inteiro e uma unidade de temperatura. Devem ser formatados como nos exemplos abaixo.

Para isso, faz com que o tipo Temperature implemente a interface Stringer, adicionando-lhe um método String. Este método deve devolver uma string com o valor numérico da temperatura e a unidade de temperatura separados por um espaço: <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. Implementa a interface Stringer para o tipo SpeedUnit

Depois de longas discussões, a equipa concordou que a unidade de velocidade do vento será KmPerHour ou MilesPerHour. Os valores devem ser formatados como nos exemplos abaixo.

Para isso, faz com que o tipo SpeedUnit implemente a interface Stringer, adicionando-lhe um método String. Este método deve devolver a string "km/h" se a unidade de velocidade for quilómetros por hora, ou "mph" se a unidade de velocidade for milhas por hora:

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

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

4. Implementa a interface Stringer para o tipo Speed

Os valores de velocidade do vento são compostos por um número inteiro e uma unidade de velocidade. Devem ser formatados como no exemplo abaixo.

Para isso, faz com que o tipo Speed implemente a interface Stringer, adicionando-lhe um método String. Este método deve devolver uma string com o valor numérico da velocidade e a unidade de velocidade separados por um espaço: <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. Implementa a interface Stringer para o tipo MeteorologyData

Os dados meteorológicos especificam a localização, a temperatura, a direção do vento, a velocidade do vento e a humidade. Devem ser formatados como no exemplo abaixo:

Para isso, faz com que o tipo MeteorologyData implemente a interface Stringer, adicionando-lhe um método String. Este método deve devolver os dados meteorológicos no seguinte formato:

<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
Editar via GitHub A ligação abre numa nova janela ou separador
Go Exercism

Estás pronto para começar Meteorologia?

Inscreve-te no Exercism para aprenderes e dominares Go com 34 conceitos166 exercícios, e mentoria humana real, tudo grátis.