Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concept stringers with exercise #2208

Merged
merged 13 commits into from
May 29, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions concepts/stringers/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"blurb": "Stringer is an interface for defining the string format of values.",
"authors": [
"norbs57"
],
"contributors": []
}
69 changes: 69 additions & 0 deletions concepts/stringers/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# About

[Stringer][stringer-interface] is an interface for defining the string format of values.

The interface consists of a single `String` method:

```go
type Stringer interface {
String() string
}
```

Types that want to implement this interface must have a `String()` method that returns a human-friendly string representation of the type. The [fmt][fmt-package] package (and many others) will look for this method to print values.

## Example: Distances

Assume we are working on an application that deals with geographical distances measured in different units.
We have defined types `DistanceUnit` and `Distance` as follows:

```go
type DistanceUnit int

const (
Kilometer DistanceUnit = 0
Mile DistanceUnit = 1
NauticalMile DistanceUnit = 2
norbs57 marked this conversation as resolved.
Show resolved Hide resolved
)

type Distance struct {
number float64
unit DistanceUnit
}
```

These types do not implement interface `Stringer` as they lack the `String` method.
Hence `fmt` functions will print `Distance` values using Go's "default format":

```go
var distances = []Distance{
{number: 790.7, unit: Kilometer},
{number: 415.2, unit: Mile},
{number: 10_500, unit: NauticalMile},
}
fmt.Println(distances)
// Output: [{790.7 0} {415.2 1} {10500 2}]
```

In order to make the output more informative, we implement interface `Stringer` by adding a `String` method to each type:

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

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

`fmt` package functions will call these methods when formatting `Distance` values:

```go
fmt.Println(distances)
// Output: [790.7 km 415.2 mi 10500 nmi]
andrerfcsantos marked this conversation as resolved.
Show resolved Hide resolved
```

[stringer-interface]: https://pkg.go.dev/fmt#Stringer
[fmt-package]: https://pkg.go.dev/fmt
69 changes: 69 additions & 0 deletions concepts/stringers/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Introduction

[Stringer][stringer-interface] is an interface for defining the string format of values.

The interface consists of a single `String` method:

```go
type Stringer interface {
String() string
}
```

Types that want to implement this interface must have a `String()` method that returns a human-friendly string representation of the type. The [fmt][fmt-package] package (and many others) will look for this method to print values.

## Example: Distances

Assume we are working on an application that deals with geographical distances measured in different units.
We have defined types `DistanceUnit` and `Distance` as follows:

```go
type DistanceUnit int

const (
Kilometer DistanceUnit = 0
Mile DistanceUnit = 1
NauticalMile DistanceUnit = 2
)

type Distance struct {
number float64
unit DistanceUnit
}
```

These types do not implement interface `Stringer` as they lack the `String` method.
Hence `fmt` functions will print `Distance` values using Go's "default format":

```go
var distances = []Distance{
{number: 790.7, unit: Kilometer},
{number: 415.2, unit: Mile},
{number: 10_500, unit: NauticalMile},
}
fmt.Println(distances)
// Output: [{790.7 0} {415.2 1} {10500 2}]
```

In order to make the output more informative, we implement interface `Stringer` by adding a `String` method to each type:

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

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

`fmt` package functions will call these methods when formatting `Distance` values:

```go
fmt.Println(distances)
// Output: [790.7 km 415.2 mi 10500 nmi]
```

[stringer-interface]: https://pkg.go.dev/fmt#Stringer
[fmt-package]: https://pkg.go.dev/fmt
14 changes: 14 additions & 0 deletions concepts/stringers/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"url": "https://pkg.go.dev/fmt",
"description": "Go standard library: package fmt"
},
{
"url": "https://pkg.go.dev/fmt#Stringer",
"description": "Go standard library: interface Stringer"
},
{
"url": "https://go.dev/tour/methods/17",
"description": "A Tour of Go: Stringers"
}
]
21 changes: 21 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,22 @@
"slices"
],
"status": "beta"
},
{
"slug": "meteorology",
"name": "Meteorology",
"uuid": "09fc7443-f5a2-4b19-8331-f3d5df3e5165",
"concepts": [
"stringers"
],
"prerequisites": [
"strings",
"string-formatting",
"interfaces",
"methods",
"structs"
],
"status": "beta"
}
],
"practice": [
Expand Down Expand Up @@ -2067,6 +2083,11 @@
"slug": "strings-package",
"uuid": "33708451-a03f-44ce-be05-eaacc1d5793c"
},
{
"name": "Stringers",
"slug": "stringers",
"uuid": "288c0d5b-173a-4446-b9a6-05f91fddd63e"
},
{
"name": "Structs",
"slug": "structs",
Expand Down
23 changes: 23 additions & 0 deletions exercises/concept/meteorology/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Hints

## 1. Implement the `Stringer` interface for type `TemperatureUnit`

See [yourbasic.org][yourbasic-enum] for an example how to define a "enum" type with a `String` method.
andrerfcsantos marked this conversation as resolved.
Show resolved Hide resolved

## 2. Implement the `Stringer` interface for type `Temperature`

See [yourbasic.org][yourbasic-enum] for an example how to define a "enum" type with a `String` method.

## 3. Implement the `Stringer` interface for type `SpeedUnit`

See [yourbasic.org][yourbasic-enum] for an example how to define a "enum" type with a `String` method.

## 4. Implement the `Stringer` interface for `Speed`

See [yourbasic.org][yourbasic-enum] for an example how to define a "enum" type with a `String` method.

## 5. Implement the `Stringer` interface for type `MetData`

See [yourbasic.org][yourbasic-enum] for an example how to define a "enum" type with a `String` method.

[yourbasic-enum]: https://yourbasic.org/golang/iota/#complete-enum-type-with-strings-best-practice
57 changes: 57 additions & 0 deletions exercises/concept/meteorology/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Instructions

Your team is working on a meteorology application.
They have defined an API with various types and constants representing meteorological data, see file `meteorology.go`.

Your task is to add suitable `String` methods to all types so that they implement interface `Stringer`.
andrerfcsantos marked this conversation as resolved.
Show resolved Hide resolved

## 1. Implement the `Stringer` interface for type `TemperatureUnit`

After some discussion, the team have agreed that the unit of temperature will be either `Celsius` or `Fahrenheit`. Values should be formatted as shown below:

```go
andrerfcsantos marked this conversation as resolved.
Show resolved Hide resolved
temperatureUnit := Celsius
fmt.Println(temperatureUnit)
andrerfcsantos marked this conversation as resolved.
Show resolved Hide resolved
// Output: C
```

## 2. Implement the `Stringer` interface for type `Temperature`

Temperature values consist of an integer and a temperature unit. They should be formatted as in the example below:

```go
temperature := Temperature{21, Celsius}
fmt.Println(temperature)
// Output: 21 °C
```

## 3. Implement the `Stringer` interface for type `SpeedUnit`

After lengthy discussions, thee team has agreed that the unit of wind speed will be either `KmPerHour` or `MilesPerHour`. Values should be formatted as shown below:

```go
speedUnit := MilesPerHour
fmt.Println(speedUnit)
// Output: mph
```

## 4. Implement the `Stringer` interface for `Speed`

Wind speed values consist of an integer and a speed unit. They should be formatted as in the example below:

```go
windSpeed := Speed{18, KmPerHour}
fmt.Println(windSpeed)
// Output: 18 km/h
```

## 5. Implement the `Stringer` interface for type `MetData`

Meteorological data specifies location, temperature, wind direction, wind speed
and humidity. It should be formatted as in the example below:

```go
metData := MetData{"San Francisco", Temperature{57, Fahrenheit}, "NW", Speed{19, MilesPerHour}, 60}
fmt.Println(metData)
// Output: San Francisco: 57 °F, Wind NW at 19 mph, 60% Humidity
```
69 changes: 69 additions & 0 deletions exercises/concept/meteorology/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Introduction

[Stringer][stringer-interface] is an interface for defining the string format of values.

The interface consists of a single `String` method:

```go
type Stringer interface {
String() string
}
```

Types that want to implement this interface must have a `String()` method that returns a human-friendly string representation of the type. The [fmt][fmt-package] package (and many others) will look for this method to print values.

## Example: Distances

Assume we are working on an application that deals with geographical distances measured in different units.
We have defined types `DistanceUnit` and `Distance` as follows:

```go
type DistanceUnit int

const (
Kilometer DistanceUnit = 0
Mile DistanceUnit = 1
NauticalMile DistanceUnit = 2
)

type Distance struct {
number float64
unit DistanceUnit
}
```

These types do not implement interface `Stringer` as they lack the `String` method.
Hence `fmt` functions will print `Distance` values using Go's "default format":

```go
var distances = []Distance{
{number: 790.7, unit: Kilometer},
{number: 415.2, unit: Mile},
{number: 10_500, unit: NauticalMile},
}
fmt.Println(distances)
// Output: [{790.7 0} {415.2 1} {10500 2}]
```

In order to make the output more informative, we implement interface `Stringer` by adding a `String` method to each type:

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

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

`fmt` package functions will call these methods when formatting `Distance` values:

```go
fmt.Println(distances)
// Output: [790.7 km 415.2 mi 10500 nmi]
```

[stringer-interface]: https://pkg.go.dev/fmt#Stringer
[fmt-package]: https://pkg.go.dev/fmt
18 changes: 18 additions & 0 deletions exercises/concept/meteorology/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"blurb": "Learn how to work with interface Stringer",
"authors": [
"norbs57"
],
"contributors": [],
"files": {
"solution": [
"meteorology.go"
],
"test": [
"meteorology_test.go"
],
"exemplar": [
".meta/exemplar.go"
]
}
}
Loading