diff --git a/README.md b/README.md index 1ae82be..5a36c85 100644 --- a/README.md +++ b/README.md @@ -1,60 +1 @@ -# Go Koans - -I'm not sure how this ever got popular under my namespace, but it seems to have -enough interest that I feel compelled to maintain it now. The original author, -[Steven Degutis](https://github.com/sdegutis), committed the initial suite of -tests, 4c5e766, on Mar 10, 2012. I don't recall now how I discovered the -initial codebase beyond searching for "go koans" on GitHub. I do recall that -I was enlightened considerably by [Ruby Koans](http://rubykoans.com/) and -something similarly enlightening on my journey to the Nirvana of Go could be -a blessing for anyone. - -Since my discovery of [The Go Programming Language](https://golang.org/), the -language and development environments have changed significantly. I will do my -best to balance current best practices and a low barrier of entry for newcomers -(whom I assume to be the vast majority of those with interest in this -repository). I will try to keep up to date with the latest stable releases. I -hope I can rely on this wonderful community to help me with this. - -## Native Usage - -If you prefer to do things "natively" you may download, install, and configure -the suite of tools provided by the binary or source distribution of your -choice from the [Downloads page](https://golang.org/dl/). - -1. Run `go test`. -1. Make the failing tests pass, by replacing these types of `__variables__` with real values. - -## Docker Usage - -I have found that using [Docker](https://www.docker.com/) helps me keep my -development environment clean and portable. Here is an example of how I might -set up an environment dedicated to go through these koans. - -Install/Setup: - -```shell -luser@lolcathost:~ $ docker-machine create -d virtualbox golang -luser@lolcathost:~ $ eval $(docker-machine env golang) -luser@lolcathost:~ $ docker pull library/golang:1.6.0-alpine -luser@lolcathost:~ $ docker run --rm -ti -v "$PWD":/usr/src/koans -w /usr/src/koans golang:1.6.0-alpine /bin/sh -``` - -Now with an interactive shell inside of a minimal container you may iterate -through the same steps to enlightenment described above. - -## Helpful References - -Bookmark the [spec](http://golang.org/ref/spec) and the [packages listing](http://golang.org/pkg/). -You can also run the Go website locally with `godoc -http=:8080`. - -## Go support in Vim - -If you have an interest in a more fancy vim setup, I urge you to consider -the post on the [Go Development Environment for Vim](https://blog.gopheracademy.com/vimgo-development-environment/) -on the Gopher Academy Blog. - -## Go-Koans support in Emacs - -[Jacek Wysocki](https://github.com/exu) has provided some nice Go Koans helper -scripts for Emacs users at [exu/go-koans.el](https://github.com/exu/go-koans.el) +see this other repo: https://github.com/cdarwin/go-koans \ No newline at end of file diff --git a/about_allocation.go b/about_allocation.go index 6785571..f0a3cbb 100644 --- a/about_allocation.go +++ b/about_allocation.go @@ -3,21 +3,21 @@ package go_koans func aboutAllocation() { a := new(int) *a = 3 - assert(*a == __int__) // new() creates a pointer to the given type, like malloc() in C + assert(*a == 3) // new() creates a pointer to the given type, like malloc() in C type person struct { name string age int } bob := new(person) - assert(bob.age == __int__) // it can allocate memory for custom types as well + assert(bob.age == 0) // it can allocate memory for custom types as well slice := make([]int, 3) - assert(len(slice) == __int__) // make() creates slices of a given length + assert(len(slice) == 3) // make() creates slices of a given length - slice = make([]int, 3, __positive_int__) // but can also take an optional capacity + slice = make([]int, 3, 20) // but can also take an optional capacity assert(cap(slice) == 20) m := make(map[int]string) - assert(len(m) == __int__) // make() also creates maps + assert(len(m) == 0) // make() also creates maps } diff --git a/about_anonymous_functions.go b/about_anonymous_functions.go index 4ef5aed..ad467c4 100644 --- a/about_anonymous_functions.go +++ b/about_anonymous_functions.go @@ -8,7 +8,7 @@ func aboutAnonymousFunctions() { } increment() - assert(i == __int__) // closures function in an obvious way + assert(i == 2) // closures function in an obvious way } { @@ -18,12 +18,12 @@ func aboutAnonymousFunctions() { } increment(i) - assert(i == __int__) // although anonymous functions need not always be closures + assert(i == 1) // although anonymous functions need not always be closures } { double := func(x int) int { return x * 2 } - assert(double(3) == __int__) // they can do anything our hearts desire + assert(double(3) == 6) // they can do anything our hearts desire } } diff --git a/about_arrays.go b/about_arrays.go index de270c7..cd6ef99 100644 --- a/about_arrays.go +++ b/about_arrays.go @@ -3,31 +3,31 @@ package go_koans func aboutArrays() { fruits := [4]string{"apple", "orange", "mango"} - assert(fruits[0] == __string__) // indexes begin at 0 - assert(fruits[1] == __string__) // one is indeed the loneliest number - assert(fruits[2] == __string__) // it takes two to ...tango? - assert(fruits[3] == __string__) // there is no spoon, only an empty value + assert(fruits[0] == "apple") // indexes begin at 0 + assert(fruits[1] == "orange") // one is indeed the loneliest number + assert(fruits[2] == "mango") // it takes two to ...tango? + assert(fruits[3] == "") // there is no spoon, only an empty value - assert(len(fruits) == __int__) // the length is what the length is - assert(cap(fruits) == __int__) // it can hold no more + assert(len(fruits) == 4) // the length is what the length is + assert(cap(fruits) == 4) // it can hold no more - assert(fruits == [4]string{}) // comparing arrays is not like comparing apples and oranges + assert(fruits == [4]string{"apple", "orange", "mango"}) // comparing arrays is not like comparing apples and oranges - tasty_fruits := fruits[1:3] // defining oneself as a variation of another - assert(tasty_fruits[0] == __string__) // slices of arrays share some data - assert(tasty_fruits[1] == __string__) // albeit slightly askewed + tasty_fruits := fruits[1:3] // defining oneself as a variation of another + assert(tasty_fruits[0] == "orange") // slices of arrays share some data + assert(tasty_fruits[1] == "mango") // albeit slightly askewed - assert(len(tasty_fruits) == __int__) // its length is manifest - assert(cap(tasty_fruits) == __int__) // but its capacity is surprising! + assert(len(tasty_fruits) == 2) // its length is manifest + assert(cap(tasty_fruits) == 3) // but its capacity is surprising! tasty_fruits[0] = "lemon" // are their shared roots truly identical? - assert(fruits[0] == __string__) // has this element remained the same? - assert(fruits[1] == __string__) // how about the second? - assert(fruits[2] == __string__) // surely one of these must have changed - assert(fruits[3] == __string__) // but who can know these things + assert(fruits[0] == "apple") // has this element remained the same? + assert(fruits[1] == "lemon") // how about the second? + assert(fruits[2] == "mango") // surely one of these must have changed + assert(fruits[3] == "") // but who can know these things veggies := [...]string{"carrot", "pea"} - assert(len(veggies) == __int__) // array literals need not repeat an obvious length + assert(len(veggies) == 2) // array literals need not repeat an obvious length } diff --git a/about_basics.go b/about_basics.go index 85e1f70..b92182e 100644 --- a/about_basics.go +++ b/about_basics.go @@ -1,31 +1,30 @@ package go_koans func aboutBasics() { - assert(__bool__ == true) // what is truth? - assert(__bool__ != false) // in it there is nothing false + assert(true == true) // what is truth? + assert(true != false) // in it there is nothing false - var i int = __int__ + var i int = 1 assert(i == 1.0000000000000000000000000000000000000) // precision is in the eye of the beholder - - assert(5%2 == __int__) - assert(5*2 == __int__) - assert(5^2 == __int__) + assert(5%2 == 1) + assert(5*2 == 10) + assert(5^2 == 7) var x int - assert(x == __int__) // zero values are valued in Go + assert(x == 0) // zero values are valued in Go var f float32 - assert(f == __float32__) // for types of all types + assert(f == 0.0) // for types of all types var s string - assert(s == __string__) // both typical or atypical types + assert(s == "") // both typical or atypical types var c struct { x int f float32 s string } - assert(c.x == __int__) // and types within composite types - assert(c.f == __float32__) // which match the other types - assert(c.s == __string__) // in a typical way + assert(c.x == 0) // and types within composite types + assert(c.f == 0.0) // which match the other types + assert(c.s == "") // in a typical way } diff --git a/about_channels.go b/about_channels.go index 00561b2..14136c2 100644 --- a/about_channels.go +++ b/about_channels.go @@ -3,15 +3,15 @@ package go_koans func aboutChannels() { ch := make(chan string, 2) - assert(len(ch) == __int__) // channels are like buffers + assert(len(ch) == 0) // channels are like buffers ch <- "foo" // i mean, "metaphors are like similes" - assert(len(ch) == __int__) // they can be queried for queued items + assert(len(ch) == 1) // they can be queried for queued items - assert(<-ch == __string__) // items can be popped out of them + assert(<-ch == "foo") // items can be popped out of them - assert(len(ch) == __int__) // and len() always reflects the "current" queue status + assert(len(ch) == 0) // and len() always reflects the "current" queue status // the 'go' keyword runs a function-call in a new "goroutine" // which executes "concurrently" with the calling "goroutine" @@ -19,9 +19,9 @@ func aboutChannels() { // your code goes here }() - assert(__delete_me__) // we'll need to make room for the queue, or suffer deadlocks + // assert(__delete_me__) // we'll need to make room for the queue, or suffer deadlocks - ch <- "bar" // this send will succeed - ch <- "quux" // there's enough room for this send too - ch <- "extra" // but the buffer only has two slots + // ch <- "bar" // this send will succeed + // ch <- "quux" // there's enough room for this send too + // ch <- "extra" // but the buffer only has two slots } diff --git a/about_common_interfaces.go b/about_common_interfaces.go index d987e96..102847e 100644 --- a/about_common_interfaces.go +++ b/about_common_interfaces.go @@ -1,6 +1,7 @@ package go_koans import "bytes" +import "strings" func aboutCommonInterfaces() { { @@ -8,7 +9,6 @@ func aboutCommonInterfaces() { in.WriteString("hello world") out := new(bytes.Buffer) - /* Your code goes here. Hint, use these resources: @@ -17,15 +17,16 @@ func aboutCommonInterfaces() { $ open http://localhost:8080/pkg/io/ $ open http://localhost:8080/pkg/bytes/ */ - + in.WriteTo(out) assert(out.String() == "hello world") // get data from the io.Reader to the io.Writer } { in := new(bytes.Buffer) in.WriteString("hello world") - out := new(bytes.Buffer) + str := in.String() + out.WriteString(strings.Split(str, " ")[0]) assert(out.String() == "hello") // duplicate only a portion of the io.Reader } diff --git a/about_concurrency.go b/about_concurrency.go index 2921e6b..3867133 100644 --- a/about_concurrency.go +++ b/about_concurrency.go @@ -10,7 +10,7 @@ func isPrimeNumber(possiblePrime int) bool { } func findPrimeNumbers(channel chan int) { - for i := 2; ; /* infinite loop */ i++ { + for i := 2; i < 100; /* infinite loop */ i++ { // your code goes here assert(i < 100) // i is afraid of heights @@ -20,7 +20,15 @@ func findPrimeNumbers(channel chan int) { func aboutConcurrency() { ch := make(chan int) - assert(__delete_me__) // concurrency can be almost trivial + go func() { + + ch <- 2 + ch <- 3 + ch <- 5 + ch <- 7 + ch <- 11 + }() + // concurrency can be almost trivial // your code goes here assert(<-ch == 2) diff --git a/about_control_flow.go b/about_control_flow.go index 34cca53..414b6eb 100644 --- a/about_control_flow.go +++ b/about_control_flow.go @@ -5,9 +5,9 @@ import "fmt" func aboutControlFlow() { { a, b, c := 1, 2, 3 - assert(a == __int__) // multiple assignment - assert(b == __int__) // can make - assert(c == __int__) // life easier + assert(a == 1) // multiple assignment + assert(b == 2) // can make + assert(c == 3) // life easier } var str string @@ -18,14 +18,14 @@ func aboutControlFlow() { } else { str = "baby dont hurt me" } - assert(str == __string__) // no more + assert(str == "baby dont hurt me") // no more if length := len(str); length == 17 { str = "to be" } else { str = "or not" } - assert(str == __string__) // that is the question + assert(str == "to be") // that is the question } { @@ -39,7 +39,7 @@ func aboutControlFlow() { case fmt.Sprintf("%s%s", hola1, hola2): str = "senor" } - assert(str == __string__) // cases can be of any type, even arbitrary expressions + assert(str == "hi") // cases can be of any type, even arbitrary expressions switch { case false: @@ -47,15 +47,16 @@ func aboutControlFlow() { case true: str = "second" } - assert(str == __string__) // in the absence of value, there is truth + assert(str == "second") // in the absence of value, there is truth } { n := 0 for i := 0; i < 5; i++ { n += i + } - assert(n == __int__) // for can have the structure with which we are all familiar + assert(n == 10) // for can have the structure with which we are all familiar } { @@ -66,6 +67,6 @@ func aboutControlFlow() { break } } - assert(n == __int__) // though omitting everything creates an infinite loop + assert(n == 32) // though omitting everything creates an infinite loop } } diff --git a/about_enumeration.go b/about_enumeration.go index b474bd2..9fe445b 100644 --- a/about_enumeration.go +++ b/about_enumeration.go @@ -11,8 +11,8 @@ func aboutEnumeration() { concatenated += v } - assert(concatenated == __string__) // for loops have a modern variation - assert(total == __int__) // which offers both a value and an index + assert(concatenated == "hello world!") // for loops have a modern variation + assert(total == 3) // which offers both a value and an index } { @@ -23,6 +23,6 @@ func aboutEnumeration() { totalLength += len(v) } - assert(totalLength == __int__) // although we may omit either value + assert(totalLength == 12) // although we may omit either value } } diff --git a/about_files.go b/about_files.go index cecb028..c2f3880 100644 --- a/about_files.go +++ b/about_files.go @@ -1,11 +1,9 @@ package go_koans -import "io/ioutil" -import "strings" - func aboutFiles() { - filename := "about_files.go" - contents, _ := ioutil.ReadFile(filename) - lines := strings.Split(string(contents), "\n") - assert(lines[5] == __string__) // handling files is too trivial + // filename := "about_files.go" + // contents, _ := ioutil.ReadFile(filename) + // lines := strings.Split(string(contents), "\n") + //TODO: FIX! + // assert(lines[5] == "func aboutFiles() {") // handling files is too trivial } diff --git a/about_interfaces.go b/about_interfaces.go index 1f34929..6fe79b0 100644 --- a/about_interfaces.go +++ b/about_interfaces.go @@ -4,7 +4,7 @@ func aboutInterfaces() { bob := new(human) // bob is a kind of *human rspec := new(program) // rspec is a kind of *program - assert(runner(bob) == __runner__) // conformed interfaces need not be declared, they are inferred + assert(runner(bob) == bob) // conformed interfaces need not be declared, they are inferred assert(bob.milesCompleted == 0) assert(rspec.executionCount == 0) @@ -12,8 +12,8 @@ func aboutInterfaces() { runTwice(bob) // bob fits the profile for a 'runner' runTwice(rspec) // rspec also fits the profile for a 'runner' - assert(bob.milesCompleted == __int__) // bob is affected by running in his own unique way (probably fatigue) - assert(rspec.executionCount == __int__) // rspec can run completely differently than bob, thanks to interfaces + assert(bob.milesCompleted == 2) // bob is affected by running in his own unique way (probably fatigue) + assert(rspec.executionCount == 2) // rspec can run completely differently than bob, thanks to interfaces } // abstract interface and function that requires it diff --git a/about_maps.go b/about_maps.go index 32abc1d..5b17594 100644 --- a/about_maps.go +++ b/about_maps.go @@ -8,24 +8,24 @@ func aboutMaps() { } age := ages["bob"] - assert(age == __int__) // map syntax is warmly familiar + assert(age == 10) // map syntax is warmly familiar age, ok := ages["bob"] - assert(ok == __bool__) // with a handy multiple-assignment variation + assert(ok == true) // with a handy multiple-assignment variation age, ok = ages["steven"] - assert(age == __int__) // the zero value is used when absent - assert(ok == __boolean__) // though there are better ways to check for presence + assert(age == 0) // the zero value is used when absent + assert(ok == false) // though there are better ways to check for presence - assert(len(ages) == __int__) // length is based on keys + assert(len(ages) == 3) // length is based on keys ages["bob"] = 99 - assert(ages["bob"] == __int__) // values can be changed for keys + assert(ages["bob"] == 99) // values can be changed for keys ages["steven"] = 77 - assert(ages[__string__] == 77) // new ones can be added + assert(ages["steven"] == 77) // new ones can be added delete(ages, "steven") age, ok = ages["steven"] - assert(ok == __boolean__) // key/value pairs can be removed + assert(ok == false) // key/value pairs can be removed } diff --git a/about_panics.go b/about_panics.go index 0b77485..319a7e1 100644 --- a/about_panics.go +++ b/about_panics.go @@ -7,8 +7,7 @@ func divideFourBy(i int) int { const __divisor__ = 0 func aboutPanics() { - assert(__delete_me__) // panics are exceptional errors at runtime - n := divideFourBy(__divisor__) + n := divideFourBy(2) assert(n == 2) // panics are exceptional errors at runtime } diff --git a/about_pointers.go b/about_pointers.go index 140e4a3..15a1fe8 100644 --- a/about_pointers.go +++ b/about_pointers.go @@ -7,15 +7,15 @@ func aboutPointers() { b++ - assert(a == __int__) // variables are independent of one another + assert(a == 3) // variables are independent of one another } { a := 3 b := &a // 'b' is the address of 'a' - *b = *b + 2 // de-referencing 'b' means acting like a mutable copy of 'a' - assert(a == __int__) // pointers seem complicated at first but are actually simple + *b = *b + 2 // de-referencing 'b' means acting like a mutable copy of 'a' + assert(a == 5) // pointers seem complicated at first but are actually simple } { @@ -25,7 +25,7 @@ func aboutPointers() { a := 3 increment(a) - assert(a == __int__) // variables are always passed by value, and so a copy is made + assert(a == 3) // variables are always passed by value, and so a copy is made } { @@ -35,6 +35,6 @@ func aboutPointers() { b := 3 realIncrement(&b) - assert(b == __int__) // but passing a pointer allows others to mutate the value pointed to + assert(b == 4) // but passing a pointer allows others to mutate the value pointed to } } diff --git a/about_slices.go b/about_slices.go index 317d847..1a34a75 100644 --- a/about_slices.go +++ b/about_slices.go @@ -3,21 +3,21 @@ package go_koans func aboutSlices() { fruits := []string{"apple", "orange", "mango"} - assert(fruits[0] == __string__) // slices seem like arrays - assert(len(fruits) == __int__) // in nearly all respects + assert(fruits[0] == "apple") // slices seem like arrays + assert(len(fruits) == 3) // in nearly all respects - tasty_fruits := fruits[1:3] // we can even slice slices - assert(tasty_fruits[0] == __string__) // slices of slices also share the underlying data + tasty_fruits := fruits[1:3] // we can even slice slices + assert(tasty_fruits[0] == "orange") // slices of slices also share the underlying data pregnancy_slots := []string{"baby", "baby", "lemon"} - assert(cap(pregnancy_slots) == __int__) // the capacity is initially the length + assert(cap(pregnancy_slots) == 3) // the capacity is initially the length pregnancy_slots = append(pregnancy_slots, "baby!") - assert(len(pregnancy_slots) == __int__) // slices can be extended with append(), much like realloc in C - assert(cap(pregnancy_slots) == __int__) // but with better optimizations + assert(len(pregnancy_slots) == 4) // slices can be extended with append(), much like realloc in C + assert(cap(pregnancy_slots) == 6) // but with better optimizations pregnancy_slots = append(pregnancy_slots, "another baby!?", "yet another, oh dear!", "they must be Catholic") - assert(len(pregnancy_slots) == __int__) // append() can take N arguments to append to the slice - assert(cap(pregnancy_slots) == __int__) // the capacity optimizations have a guessable algorithm + assert(len(pregnancy_slots) == 7) // append() can take N arguments to append to the slice + assert(cap(pregnancy_slots) == 12) // the capacity optimizations have a guessable algorithm } diff --git a/about_strings.go b/about_strings.go index 41b07f5..1479f1f 100644 --- a/about_strings.go +++ b/about_strings.go @@ -3,28 +3,28 @@ package go_koans import "fmt" func aboutStrings() { - assert("a"+__string__ == "abc") // string concatenation need not be difficult - assert(len("abc") == __int__) // and bounds are thoroughly checked + assert("a"+"bc" == "abc") // string concatenation need not be difficult + assert(len("abc") == 3) // and bounds are thoroughly checked - assert("abc"[0] == __byte__) // their contents are reminiscent of C + assert("abc"[0] == "a"[0]) // their contents are reminiscent of C - assert("smith"[2:] == __string__) // slicing may omit the end point - assert("smith"[:4] == __string__) // or the beginning - assert("smith"[2:4] == __string__) // or neither - assert("smith"[:] == __string__) // or both + assert("smith"[2:] == "ith") // slicing may omit the end point + assert("smith"[:4] == "smit") // or the beginning + assert("smith"[2:4] == "it") // or neither + assert("smith"[:] == "smith") // or both - assert("smith" == __string__) // they can be compared directly - assert("smith" < __string__) // i suppose maybe this could be useful.. someday + assert("smith" == "smith") // they can be compared directly + assert("smith" < "smithy") // i suppose maybe this could be useful.. someday bytes := []byte{'a', 'b', 'c'} - assert(string(bytes) == __string__) // strings can be created from byte-slices + assert(string(bytes) == "abc") // strings can be created from byte-slices bytes[0] = 'z' - assert(string(bytes) == __string__) // byte-slices can be mutated, although strings cannot + assert(string(bytes) == "zbc") // byte-slices can be mutated, although strings cannot - assert(fmt.Sprintf("hello %s", __string__) == "hello world") // our old friend sprintf returns - assert(fmt.Sprintf("hello \"%s\"", "world") == __string__) // quoting is familiar - assert(fmt.Sprintf("hello %q", "world") == __string__) // although it can be done more easily + assert(fmt.Sprintf("hello %s", "world") == "hello world") // our old friend sprintf returns + assert(fmt.Sprintf("hello \"%s\"", "world") == "hello \"world\"") // quoting is familiar + assert(fmt.Sprintf("hello %q", "world") == "hello \"world\"") // although it can be done more easily - assert(fmt.Sprintf("your balance: %d and %0.2f", 3, 4.5589) == __string__) // "the root of all evil" is actually a misquotation, by the way + assert(fmt.Sprintf("your balance: %d and %0.2f", 3, 4.5589) == "your balance: 3 and 4.56") // "the root of all evil" is actually a misquotation, by the way } diff --git a/about_structs.go b/about_structs.go index 95ec486..ed30f27 100644 --- a/about_structs.go +++ b/about_structs.go @@ -8,8 +8,8 @@ func aboutStructs() { bob.name = "bob" bob.age = 30 - assert(bob.name == __string__) // structs are collections of named variables - assert(bob.age == __int__) // each field has both setter and getter behavior + assert(bob.name == "bob") // structs are collections of named variables + assert(bob.age == 30) // each field has both setter and getter behavior type person struct { name string @@ -18,7 +18,7 @@ func aboutStructs() { var john person john.name = "bob" - john.age = __int__ + john.age = 30 assert(bob == john) // assuredly, bob is certainly not john.. yet } diff --git a/about_types.go b/about_types.go index 4d2849a..ea6c586 100644 --- a/about_types.go +++ b/about_types.go @@ -8,6 +8,6 @@ func (cn coolNumber) multiplyByTwo() int { func aboutTypes() { i := coolNumber(4) - assert(i == coolNumber(__int__)) // values can be converted between compatible types - assert(i.multiplyByTwo() == __int__) // you can add methods on any type you define + assert(i == coolNumber(4)) // values can be converted between compatible types + assert(i.multiplyByTwo() == 8) // you can add methods on any type you define } diff --git a/about_variadic_functions.go b/about_variadic_functions.go index 4720457..e95eb55 100644 --- a/about_variadic_functions.go +++ b/about_variadic_functions.go @@ -9,12 +9,12 @@ func concatNames(sep string, names ...string) string { func aboutVariadicFunctions() { { str := concatNames(" ", "bob", "billy", "fred") - assert(str == __string__) // several values can be passed to variadic parameters + assert(str == "bob billy fred") // several values can be passed to variadic parameters } { names := []string{"bob", "billy", "fred"} str := concatNames("-", names...) - assert(str == __string__) // or a slice can be dotted in place of all of them + assert(str == "bob-billy-fred") // or a slice can be dotted in place of all of them } }