You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+62-62Lines changed: 62 additions & 62 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,8 @@ Exercism exercises in Go.
7
7
8
8
## Issues/Feedback
9
9
10
-
⚠️ Please be aware that this repository currently does not accept community contributions. This [blog post](https://exercism.org/blog/freeing-our-maintainers) explains the details.
10
+
⚠️ Please be aware that this repository currently does not accept community contributions.
11
+
This [blog post](https://exercism.org/blog/freeing-our-maintainers) explains the details.
11
12
12
13
If you have any feedback or experience problems, you can bring them up in the [Go section of the Exercism forum](https://forum.exercism.org/c/programming/go/19).
13
14
@@ -20,16 +21,17 @@ You should have a [recent version of Go](http://golang.org/doc/install) installe
20
21
You will need a github account and you will need to fork exercism/go to your account.
21
22
See [GitHub Help](https://help.github.com/articles/fork-a-repo/) if you are unfamiliar with the process.
22
23
Clone your fork with the command: `git clone https://github.com/<you>/go`.
23
-
Test your clone by cding to the go directory and typing `bin/fetch-golangci-lint` and then
24
-
`bin/run-tests`. You should see tests pass for all exercises.
24
+
Test your clone by cding to the go directory and typing `bin/fetch-golangci-lint` and then`bin/run-tests`.
25
+
You should see tests pass for all exercises.
25
26
26
27
Note that unlike most other Go code, it is not necessary to clone this to your GOPATH.
27
28
This is because this repo only imports from the standard library and isn't expected to be imported by other packages.
28
29
29
30
Your Go code should be formatted using the [gofmt](https://golang.org/cmd/gofmt/) tool.
30
31
31
-
There is a [misspelling tool](https://github.com/client9/misspell). You can install and occasionally run it to
32
-
find low hanging typo problems. [#570](https://github.com/exercism/go/pull/570) It's not added into CI since it could give false positives.
32
+
There is a [misspelling tool](https://github.com/client9/misspell).
33
+
You can install and occasionally run it to find low hanging typo problems.
34
+
[#570](https://github.com/exercism/go/pull/570) It's not added into CI since it could give false positives.
33
35
34
36
## Contributing Guide
35
37
@@ -39,14 +41,12 @@ In particular, please read the [Pull Request Guidelines](https://github.com/exer
39
41
40
42
## Exercism Go style
41
43
42
-
Let's walk through an example, non-existent, exercise, which we'll call
43
-
`fizzbuzz` to see what could be included in its implementation.
44
+
Let's walk through an example, non-existent, exercise, which we'll call `fizzbuzz` to see what could be included in its implementation.
44
45
45
46
### Exercise configuration
46
47
47
-
An exercise is configured
48
-
via an entry in the exercises array in [config.json file](/config.json). If `fizzbuzz` is an optional
49
-
exercise, it would have an entry below the core exercises that might look like:
48
+
An exercise is configured via an entry in the exercises array in [config.json file](/config.json).
49
+
If `fizzbuzz` is an optional exercise, it would have an entry below the core exercises that might look like:
50
50
51
51
```json
52
52
{
@@ -59,8 +59,7 @@ exercise, it would have an entry below the core exercises that might look like:
59
59
}
60
60
```
61
61
62
-
See [Exercism Docs: config.json](https://exercism.org/docs/building/tracks/config-json)
63
-
for more info.
62
+
See [Exercism Docs: config.json](https://exercism.org/docs/building/tracks/config-json) for more info.
64
63
65
64
### Exercise files: Overview
66
65
@@ -102,8 +101,11 @@ Let's briefly describe each file:
102
101
103
102
-**fizzbuzz_test.go** - The main test file for the exercise.
104
103
105
-
-**.meta/** - Contains files not to be included when a user fetches an
106
-
exercise: See also [ignored files](#ignored-files).
104
+
-**go.mod** - The Go module file.
105
+
This should be automatically generated by the generator code.
106
+
107
+
-**.meta/** - Contains files not to be included when a user fetches an exercise.
108
+
See also [ignored files](#ignored-files).
107
109
108
110
-**.meta/description.md** - Use to generate a [track specific description](https://github.com/exercism/docs/blob/master/language-tracks/exercises/anatomy/readmes.md) of the exercise in the exercise's README.
109
111
@@ -139,14 +141,12 @@ Examples can be plain, simple, concise, even naïve, as long as they are correct
139
141
140
142
Stub files, such as _leap.go_, are a starting point for solutions.
141
143
Not all exercises need to have a stub file, only exercises early in the syllabus.
142
-
By convention, the stub file for an exercise with slug `exercise-slug`
143
-
must be named `exercise_slug.go`. This is because CI needs to delete stub files
144
-
to avoid conflicting definitions.
144
+
By convention, the stub file for an exercise with slug `exercise-slug` must be named `exercise_slug.go`.
145
+
This is because CI needs to delete stub files to avoid conflicting definitions.
145
146
146
147
### Tests
147
148
148
-
The test file is fetched for the solver and deserves
149
-
attention for consistency and appearance.
149
+
The test file is fetched for the solver and deserves attention for consistency and appearance.
150
150
151
151
The `leap` exercise makes use of data-driven tests.
152
152
Test cases are defined as data, then a test function iterates over the data.
@@ -156,60 +156,52 @@ The _cases_test.go_ file is generated by information found in [problem-specifica
156
156
To add additional test cases (e.g. test cases that only make sense for Go) add the test cases to `<exercise>_test.go`.
157
157
An example of using additional test cases can be found in the exercise [two-bucket](exercises/practice/two-bucket/two_bucket_test.go).
158
158
159
-
Identifiers within the test function appear in actual-expected order as described
160
-
at [Useful Test Failures](https://github.com/golang/go/wiki/CodeReviewComments#useful-test-failures).
161
-
Here the identifier `observed` is used instead of actual. That's fine. More
162
-
common are words `got` and `want`. They are clear and short. Note [Useful Test
is part of [Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).
159
+
Identifiers within the test function appear in actual-expected order as described at [Useful Test Failures](https://github.com/golang/go/wiki/CodeReviewComments#useful-test-failures).
160
+
Here the identifier `observed` is used instead of actual.
161
+
That's fine.
162
+
More common are words `got` and `want`.
163
+
They are clear and short.
164
+
Note [Useful Test Failures](https://github.com/golang/go/wiki/CodeReviewComments#useful-test-failures)is part of [Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).
165
165
Really we like most of the advice on that page.
166
166
167
167
In Go we generally have all tests enabled and do not ask the solver to edit the test program, to enable progressive tests for example.
168
168
`t.Fatalf()`, as seen in the _leap_test.go_ file, will stop tests at the first failure encountered, so the solver is not faced with too many failures at once.
169
169
170
170
### Testable examples
171
171
172
-
Some exercises can contain [Example tests](https://blog.golang.org/examples)
173
-
that document the exercise API. These examples are run alongside the standard
174
-
exercise tests and will verify that the exercise API is working as expected.
175
-
They are not required by all exercises and are not intended to replace the
176
-
data-driven tests. They are most useful for providing examples of how an
177
-
exercise's API is used. Have a look at the example tests in the [clock exercise](https://github.com/exercism/go/blob/master/exercises/clock/example_clock_test.go)
178
-
to see them in action.
172
+
Some exercises can contain [Example tests](https://blog.golang.org/examples) that document the exercise API.
173
+
These examples are run alongside the standard exercise tests and will verify that the exercise API is working as expected.
174
+
They are not required by all exercises and are not intended to replace the data-driven tests.
175
+
They are most useful for providing examples of how an exercise's API is used.
176
+
Have a look at the example tests in the [clock exercise](https://github.com/exercism/go/blob/master/exercises/clock/example_clock_test.go) to see them in action.
179
177
180
178
### Errors
181
179
182
-
We like errors in Go. It's not idiomatic Go to ignore invalid data or have undefined
183
-
behavior. Sometimes our Go tests require an error return where other language
184
-
tracks don't.
180
+
We like errors in Go.
181
+
It's not idiomatic Go to ignore invalid data or have undefined behavior.
182
+
Sometimes our Go tests require an error return where other language tracks don't.
185
183
186
184
### Benchmarks
187
185
188
-
In most test files there will also be benchmark tests, as can be seen at the end
189
-
of the _leap_test.go_ file. In Go, benchmarking is a first-class citizen of the
190
-
testing package. We throw in benchmarks because they're interesting, and because
191
-
it is idiomatic in Go to think about performance. There is no critical use for
192
-
these though. Usually they will just bench the combined time to run over all
193
-
the test data rather than attempt precise timings on single function calls. They
194
-
are useful if they let the solver try a change and see a performance effect.
186
+
In most test files there will also be benchmark tests, as can be seen at the end of the _leap_test.go_ file.
187
+
In Go, benchmarking is a first-class citizen of the testing package.
188
+
We throw in benchmarks because they're interesting, and because it is idiomatic in Go to think about performance.
189
+
There is no critical use for these though.
190
+
Usually they will just bench the combined time to run over all the test data rather than attempt precise timings on single function calls.
191
+
They are useful if they let the solver try a change and see a performance effect.
195
192
196
193
## Synchronizing exercises with problem specifications
197
194
198
-
Some problems that are implemented in multiple tracks use the same inputs and
199
-
outputs to define the test suites.
200
-
Where the [problem-specifications](https://github.com/exercism/problem-specifications)
201
-
repository contains a _canonical-data.json_ file with these inputs and outputs,
202
-
we can generate the test cases programmatically.
195
+
Some problems that are implemented in multiple tracks use the same inputs and outputs to define the test suites.
196
+
Where the [problem-specifications](https://github.com/exercism/problem-specifications) repository contains a _canonical-data.json_ file with these inputs and outputs, we can generate the test cases programmatically.
203
197
The problem-specifications repo also defines the instructions for the exercises, which are also shared across tracks and must also be synchronized.
204
198
205
199
### Test structure
206
200
207
-
See the _gen.go_ file in the `leap` exercise for an example of how this
208
-
can be done.
201
+
See the _gen.go_ file in the `leap` exercise for an example of how this can be done.
209
202
210
-
Test case generators are named _gen.go_ and are kept in a special _.meta_
211
-
directory within each exercise that makes use of a test cases generator. This
212
-
_.meta_ directory will be ignored when a user fetches an exercise.
203
+
Test case generators are named _gen.go_ and are kept in a special _.meta_ directory within each exercise that makes use of a test cases generator.
204
+
This _.meta_ directory will be ignored when a user fetches an exercise.
213
205
214
206
Whenever the shared JSON data changes, the test cases will need to be regenerated.
215
207
The generator will first look for a local copy of the **problem-specifications** repository.
@@ -229,7 +221,7 @@ $ tree -L 1 .
229
221
230
222
#### Adding a test generator to an exercise
231
223
232
-
For some exercises, a test generator is used to generate the `cases_test.go` file with the test cases based on information from [problem-specifications](https://github.com/exercism/problem-specifications).
224
+
For most exercises, a test generator is used to generate the `cases_test.go` file with the test cases based on information from [problem-specifications](https://github.com/exercism/problem-specifications).
233
225
To add a new exercise generator to an exercise the following steps are needed:
234
226
1. Create the file `gen.go` in the directory `.meta` of the exercise
235
227
2. Add the following template to `gen.go`:
@@ -258,18 +250,23 @@ func main() {
258
250
}
259
251
```
260
252
3. Insert the name of the exercise to the call of `gen.Gen`
261
-
4. Add all values for the field `property` in `canonical-data.json` to the map `j`. `canonical-data.json` can be found at [problem-specifications/exercises/\<exercise-name\>](https://github.com/exercism/problem-specifications)
253
+
4. Add all values for the field `property` in `canonical-data.json` to the map `j`.
254
+
`canonical-data.json` can be found at [problem-specifications/exercises/\<exercise-name\>](https://github.com/exercism/problem-specifications)
262
255
5. Create the needed structs for storing the test cases from `canonical-data.json` (you can for example use [JSON-to-Go](https://mholt.github.io/json-to-go/) to convert the JSON to a struct)
263
256
264
-
**NOTE:** In some cases, the struct of the data in the `input`/`expected` fields is not the same for all test cases of one property. In those situations, an `interface{}` has to be used to represent the values for these fields. These `interface{}` values then need to be handled by the test generator. A common way to handle these cases is to create methods on the test case structs that perform type assertions on the `interface{}` values and return something more meaningful. These methods can then be referenced/called in the `tmpl` template variable. Examples of this can be found in the exercises [forth](https://github.com/exercism/go/blob/main/exercises/practice/forth/.meta/gen.go) or [bowling](https://github.com/exercism/go/blob/main/exercises/practice/bowling/.meta/gen.go).
257
+
**NOTE:** In some cases, the struct of the data in the `input`/`expected` fields is not the same for all test cases of one property.
258
+
In those situations, an `interface{}` has to be used to represent the values for these fields.
259
+
These `interface{}` values then need to be handled by the test generator.
260
+
A common way to handle these cases is to create methods on the test case structs that perform type assertions on the `interface{}` values and return something more meaningful.
261
+
These methods can then be referenced/called in the `tmpl` template variable.
262
+
Examples of this can be found in the exercises [forth](https://github.com/exercism/go/blob/main/exercises/practice/forth/.meta/gen.go) or [bowling](https://github.com/exercism/go/blob/main/exercises/practice/bowling/.meta/gen.go).
265
263
266
-
6. Add the variable `tmpl` to `gen.go`. This template will be used to create the `cases_test.go` file.
264
+
6. Add the variable `tmpl` to `gen.go`.
265
+
This template will be used to create the `cases_test.go` file.
267
266
268
267
Example:
269
268
```go
270
-
vartmpl = `package <package of exercise>
271
-
272
-
{{.Header}}
269
+
vartmpl = `{{.Header}}
273
270
274
271
var testCases = []struct {
275
272
description string
@@ -321,7 +318,8 @@ Try providing a GitHub access token with the flag `-github_token="<Token>"`.
321
318
Using the token will result in a higher rate limit.
322
319
The token does not need any specific scopes as it is only used to fetch infos about commits.
323
320
324
-
You should see that some/all of the above files have changed. Commit the changes.
321
+
You should see that some/all of the above files have changed.
322
+
Commit the changes.
325
323
326
324
### Synchronizing all exercises with generators
327
325
@@ -375,15 +373,17 @@ If there's a problem, it comes up red:
375
373
<imgsrc="img/mars3.png">
376
374
377
375
This means you've still got work to do.
378
-
Click on "details" to go to the CI build details. Look over the build log for clues.
376
+
Click on "details" to go to the CI build details.
377
+
Look over the build log for clues.
379
378
Usually error messages will be helpful and you can correct the problem.
380
379
381
380
## Direction
382
381
383
382
Directions are unlimited.
384
383
This code is fresh and evolving.
385
384
Explore the existing code and you will see some new directions being tried.
386
-
Your fresh ideas and contributions are welcome. :sparkles:
0 commit comments