Merge pull request #8 from qjcg/gofmt-everything
Run "go fmt" on all .go files
This commit is contained in:
@@ -1,23 +1,23 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutAllocation() {
|
func aboutAllocation() {
|
||||||
a := new(int)
|
a := new(int)
|
||||||
*a = 3
|
*a = 3
|
||||||
assert(*a == __int__) // new() creates a pointer to the given type, like malloc() in C
|
assert(*a == __int__) // new() creates a pointer to the given type, like malloc() in C
|
||||||
|
|
||||||
type person struct {
|
type person struct {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
bob := new(person)
|
bob := new(person)
|
||||||
assert(bob.age == __int__) // it can allocate memory for custom types as well
|
assert(bob.age == __int__) // it can allocate memory for custom types as well
|
||||||
|
|
||||||
slice := make([]int, 3)
|
slice := make([]int, 3)
|
||||||
assert(len(slice) == __int__) // make() creates slices of a given length
|
assert(len(slice) == __int__) // make() creates slices of a given length
|
||||||
|
|
||||||
slice = make([]int, 3, __positive_int__) // but can also take an optional capacity
|
slice = make([]int, 3, __positive_int__) // but can also take an optional capacity
|
||||||
assert(cap(slice) == 20)
|
assert(cap(slice) == 20)
|
||||||
|
|
||||||
m := make(map[int]string)
|
m := make(map[int]string)
|
||||||
assert(len(m) == __int__) // make() also creates maps
|
assert(len(m) == __int__) // make() also creates maps
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutAnonymousFunctions() {
|
func aboutAnonymousFunctions() {
|
||||||
{
|
{
|
||||||
i := 1
|
i := 1
|
||||||
increment := func() {
|
increment := func() {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
increment()
|
increment()
|
||||||
|
|
||||||
assert(i == __int__) // closures function in an obvious way
|
assert(i == __int__) // closures function in an obvious way
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
i := 1
|
i := 1
|
||||||
increment := func(x int) {
|
increment := func(x int) {
|
||||||
x++
|
x++
|
||||||
}
|
}
|
||||||
increment(i)
|
increment(i)
|
||||||
|
|
||||||
assert(i == __int__) // although anonymous functions need not always be closures
|
assert(i == __int__) // although anonymous functions need not always be closures
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
double := func(x int) int { return x * 2 }
|
double := func(x int) int { return x * 2 }
|
||||||
|
|
||||||
assert(double(3) == __int__) // they can do anything our hearts desire
|
assert(double(3) == __int__) // they can do anything our hearts desire
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutArrays() {
|
func aboutArrays() {
|
||||||
fruits := [4]string{"apple", "orange", "mango"}
|
fruits := [4]string{"apple", "orange", "mango"}
|
||||||
|
|
||||||
assert(fruits[0] == __string__) // indexes begin at 0
|
assert(fruits[0] == __string__) // indexes begin at 0
|
||||||
assert(fruits[1] == __string__) // one is indeed the loneliest number
|
assert(fruits[1] == __string__) // one is indeed the loneliest number
|
||||||
assert(fruits[2] == __string__) // it takes two to ...tango?
|
assert(fruits[2] == __string__) // it takes two to ...tango?
|
||||||
assert(fruits[3] == __string__) // there is no spoon, only an empty value
|
assert(fruits[3] == __string__) // there is no spoon, only an empty value
|
||||||
|
|
||||||
assert(len(fruits) == __int__) // the length is what the length is
|
assert(len(fruits) == __int__) // the length is what the length is
|
||||||
assert(cap(fruits) == __int__) // it can hold no more
|
assert(cap(fruits) == __int__) // it can hold no more
|
||||||
|
|
||||||
assert(fruits == [4]string{}) // comparing arrays is not like comparing apples and oranges
|
assert(fruits == [4]string{}) // comparing arrays is not like comparing apples and oranges
|
||||||
|
|
||||||
tasty_fruits := fruits[1:3] // defining oneself as a variation of another
|
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[0] == __string__) // slices of arrays share some data
|
||||||
assert(tasty_fruits[1] == __string__) // albeit slightly askewed
|
assert(tasty_fruits[1] == __string__) // albeit slightly askewed
|
||||||
|
|
||||||
assert(len(tasty_fruits) == __int__) // its length is manifest
|
assert(len(tasty_fruits) == __int__) // its length is manifest
|
||||||
assert(cap(tasty_fruits) == __int__) // but its capacity is surprising!
|
assert(cap(tasty_fruits) == __int__) // but its capacity is surprising!
|
||||||
|
|
||||||
tasty_fruits[0] = "lemon" // are their shared roots truly identical?
|
tasty_fruits[0] = "lemon" // are their shared roots truly identical?
|
||||||
|
|
||||||
assert(fruits[0] == __string__) // has this element remained the same?
|
assert(fruits[0] == __string__) // has this element remained the same?
|
||||||
assert(fruits[1] == __string__) // how about the second?
|
assert(fruits[1] == __string__) // how about the second?
|
||||||
assert(fruits[2] == __string__) // surely one of these must have changed
|
assert(fruits[2] == __string__) // surely one of these must have changed
|
||||||
assert(fruits[3] == __string__) // but who can know these things
|
assert(fruits[3] == __string__) // but who can know these things
|
||||||
|
|
||||||
veggies := [...]string{"carrot", "pea"}
|
veggies := [...]string{"carrot", "pea"}
|
||||||
|
|
||||||
assert(len(veggies) == __int__) // array literals need not repeat an obvious length
|
assert(len(veggies) == __int__) // array literals need not repeat an obvious length
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutBasics() {
|
func aboutBasics() {
|
||||||
assert(__bool__ == true) // what is truth?
|
assert(__bool__ == true) // what is truth?
|
||||||
assert(__bool__ != false) // in it there is nothing false
|
assert(__bool__ != false) // in it there is nothing false
|
||||||
|
|
||||||
var i int = __int__
|
var i int = __int__
|
||||||
assert(i == 1.0000000000000000000000000000000000000) // precision is in the eye of the beholder
|
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 == __int__)
|
||||||
assert(5 ^ 2 == __int__)
|
assert(5^2 == __int__)
|
||||||
|
|
||||||
var x int
|
var x int
|
||||||
assert(x == __int__) // zero values are valued in Go
|
assert(x == __int__) // zero values are valued in Go
|
||||||
|
|
||||||
var f float32
|
var f float32
|
||||||
assert(f == __float32__) // for types of all types
|
assert(f == __float32__) // for types of all types
|
||||||
|
|
||||||
var s string
|
var s string
|
||||||
assert(s == __string__) // both typical or atypical types
|
assert(s == __string__) // both typical or atypical types
|
||||||
|
|
||||||
var c struct {
|
var c struct {
|
||||||
x int
|
x int
|
||||||
f float32
|
f float32
|
||||||
s string
|
s string
|
||||||
}
|
}
|
||||||
assert(c.x == __int__) // and types within composite types
|
assert(c.x == __int__) // and types within composite types
|
||||||
assert(c.f == __float32__) // which match the other types
|
assert(c.f == __float32__) // which match the other types
|
||||||
assert(c.s == __string__) // in a typical way
|
assert(c.s == __string__) // in a typical way
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutChannels() {
|
func aboutChannels() {
|
||||||
ch := make(chan string, 2)
|
ch := make(chan string, 2)
|
||||||
|
|
||||||
assert(len(ch) == __int__) // channels are like buffers
|
assert(len(ch) == __int__) // channels are like buffers
|
||||||
|
|
||||||
ch <- "foo" // i mean, "metaphors are like similes"
|
ch <- "foo" // i mean, "metaphors are like similes"
|
||||||
|
|
||||||
assert(len(ch) == __int__) // they can be queried for queued items
|
assert(len(ch) == __int__) // they can be queried for queued items
|
||||||
|
|
||||||
assert(<-ch == __string__) // items can be popped out of them
|
assert(<-ch == __string__) // items can be popped out of them
|
||||||
|
|
||||||
assert(len(ch) == __int__) // and len() always reflects the "current" queue status
|
assert(len(ch) == __int__) // and len() always reflects the "current" queue status
|
||||||
|
|
||||||
// the 'go' keyword runs a function-call in a new "goroutine"
|
// the 'go' keyword runs a function-call in a new "goroutine"
|
||||||
// which executes "concurrently" with the calling "goroutine"
|
// which executes "concurrently" with the calling "goroutine"
|
||||||
go func() {
|
go func() {
|
||||||
// your code goes here
|
// 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 <- "bar" // this send will succeed
|
||||||
ch <- "quux" // there's enough room for this send too
|
ch <- "quux" // there's enough room for this send too
|
||||||
ch <- "extra" // but the buffer only has two slots
|
ch <- "extra" // but the buffer only has two slots
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,30 +3,30 @@ package go_koans
|
|||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
func aboutCommonInterfaces() {
|
func aboutCommonInterfaces() {
|
||||||
{
|
{
|
||||||
in := new(bytes.Buffer)
|
in := new(bytes.Buffer)
|
||||||
in.WriteString("hello world")
|
in.WriteString("hello world")
|
||||||
|
|
||||||
out := new(bytes.Buffer)
|
out := new(bytes.Buffer)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Your code goes here.
|
Your code goes here.
|
||||||
Hint, use these resources:
|
Hint, use these resources:
|
||||||
|
|
||||||
$ godoc -http=:8080
|
$ godoc -http=:8080
|
||||||
$ open http://localhost:8080/pkg/io/
|
$ open http://localhost:8080/pkg/io/
|
||||||
$ open http://localhost:8080/pkg/bytes/
|
$ open http://localhost:8080/pkg/bytes/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
assert(out.String() == "hello world") // get data from the io.Reader to the io.Writer
|
assert(out.String() == "hello world") // get data from the io.Reader to the io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
in := new(bytes.Buffer)
|
in := new(bytes.Buffer)
|
||||||
in.WriteString("hello world")
|
in.WriteString("hello world")
|
||||||
|
|
||||||
out := new(bytes.Buffer)
|
out := new(bytes.Buffer)
|
||||||
|
|
||||||
assert(out.String() == "hello") // duplicate only a portion of the io.Reader
|
assert(out.String() == "hello") // duplicate only a portion of the io.Reader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func isPrimeNumber(possiblePrime int) bool {
|
func isPrimeNumber(possiblePrime int) bool {
|
||||||
for underPrime := 2; underPrime < possiblePrime; underPrime++ {
|
for underPrime := 2; underPrime < possiblePrime; underPrime++ {
|
||||||
if possiblePrime % underPrime == 0 {
|
if possiblePrime%underPrime == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func findPrimeNumbers(channel chan int) {
|
func findPrimeNumbers(channel chan int) {
|
||||||
for i := 2; /* infinite loop */ ; i++ {
|
for i := 2; ; /* infinite loop */ i++ {
|
||||||
// your code goes here
|
// your code goes here
|
||||||
|
|
||||||
assert(i < 100) // i is afraid of heights
|
assert(i < 100) // i is afraid of heights
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func aboutConcurrency() {
|
func aboutConcurrency() {
|
||||||
ch := make(chan int)
|
ch := make(chan int)
|
||||||
|
|
||||||
assert(__delete_me__) // concurrency can be almost trivial
|
assert(__delete_me__) // concurrency can be almost trivial
|
||||||
// your code goes here
|
// your code goes here
|
||||||
|
|
||||||
assert(<-ch == 2)
|
assert(<-ch == 2)
|
||||||
assert(<-ch == 3)
|
assert(<-ch == 3)
|
||||||
assert(<-ch == 5)
|
assert(<-ch == 5)
|
||||||
assert(<-ch == 7)
|
assert(<-ch == 7)
|
||||||
assert(<-ch == 11)
|
assert(<-ch == 11)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,69 +3,69 @@ package go_koans
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func aboutControlFlow() {
|
func aboutControlFlow() {
|
||||||
{
|
{
|
||||||
a, b, c := 1, 2, 3
|
a, b, c := 1, 2, 3
|
||||||
assert(a == __int__) // multiple assignment
|
assert(a == __int__) // multiple assignment
|
||||||
assert(b == __int__) // can make
|
assert(b == __int__) // can make
|
||||||
assert(c == __int__) // life easier
|
assert(c == __int__) // life easier
|
||||||
}
|
}
|
||||||
|
|
||||||
var str string
|
var str string
|
||||||
|
|
||||||
{
|
{
|
||||||
if 3.14 == 3 {
|
if 3.14 == 3 {
|
||||||
str = "what is love?"
|
str = "what is love?"
|
||||||
} else {
|
} else {
|
||||||
str = "baby dont hurt me"
|
str = "baby dont hurt me"
|
||||||
}
|
}
|
||||||
assert(str == __string__) // no more
|
assert(str == __string__) // no more
|
||||||
|
|
||||||
if length := len(str); length == 17 {
|
if length := len(str); length == 17 {
|
||||||
str = "to be"
|
str = "to be"
|
||||||
} else {
|
} else {
|
||||||
str = "or not"
|
str = "or not"
|
||||||
}
|
}
|
||||||
assert(str == __string__) // that is the question
|
assert(str == __string__) // that is the question
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
hola1, hola2 := "ho", "la"
|
hola1, hola2 := "ho", "la"
|
||||||
|
|
||||||
switch "hello" {
|
switch "hello" {
|
||||||
case "hello":
|
case "hello":
|
||||||
str = "hi"
|
str = "hi"
|
||||||
case "world":
|
case "world":
|
||||||
str = "planet"
|
str = "planet"
|
||||||
case fmt.Sprintf("%s%s", hola1, hola2):
|
case fmt.Sprintf("%s%s", hola1, hola2):
|
||||||
str = "senor"
|
str = "senor"
|
||||||
}
|
}
|
||||||
assert(str == __string__) // cases can be of any type, even arbitrary expressions
|
assert(str == __string__) // cases can be of any type, even arbitrary expressions
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case false:
|
case false:
|
||||||
str = "first"
|
str = "first"
|
||||||
case true:
|
case true:
|
||||||
str = "second"
|
str = "second"
|
||||||
}
|
}
|
||||||
assert(str == __string__) // in the absence of value, there is truth
|
assert(str == __string__) // in the absence of value, there is truth
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
n := 0
|
n := 0
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
n += i
|
n += i
|
||||||
}
|
}
|
||||||
assert(n == __int__) // for can have the structure with which we are all familiar
|
assert(n == __int__) // for can have the structure with which we are all familiar
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
n := 1
|
n := 1
|
||||||
for {
|
for {
|
||||||
n *= 2
|
n *= 2
|
||||||
if n > 20 {
|
if n > 20 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(n == __int__) // though omitting everything creates an infinite loop
|
assert(n == __int__) // though omitting everything creates an infinite loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutEnumeration() {
|
func aboutEnumeration() {
|
||||||
{
|
{
|
||||||
var concatenated string
|
var concatenated string
|
||||||
var total int
|
var total int
|
||||||
|
|
||||||
strings := []string{"hello", " world", "!"}
|
strings := []string{"hello", " world", "!"}
|
||||||
for i, v := range strings {
|
for i, v := range strings {
|
||||||
total += i
|
total += i
|
||||||
concatenated += v
|
concatenated += v
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(concatenated == __string__) // for loops have a modern variation
|
assert(concatenated == __string__) // for loops have a modern variation
|
||||||
assert(total == __int__) // which offers both a value and an index
|
assert(total == __int__) // which offers both a value and an index
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var totalLength int
|
var totalLength int
|
||||||
|
|
||||||
strings := []string{"hello", " world", "!"}
|
strings := []string{"hello", " world", "!"}
|
||||||
for _, v := range strings {
|
for _, v := range strings {
|
||||||
totalLength += len(v)
|
totalLength += len(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(totalLength == __int__) // although we may omit either value
|
assert(totalLength == __int__) // although we may omit either value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import "io/ioutil"
|
|||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
func aboutFiles() {
|
func aboutFiles() {
|
||||||
filename := "about_files.go"
|
filename := "about_files.go"
|
||||||
contents, _ := ioutil.ReadFile(filename)
|
contents, _ := ioutil.ReadFile(filename)
|
||||||
lines := strings.Split(string(contents), "\n")
|
lines := strings.Split(string(contents), "\n")
|
||||||
assert(lines[5] == __string__) // handling files is too trivial
|
assert(lines[5] == __string__) // handling files is too trivial
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutInterfaces() {
|
func aboutInterfaces() {
|
||||||
bob := new(human) // bob is a kind of *human
|
bob := new(human) // bob is a kind of *human
|
||||||
rspec := new(program) // rspec is a kind of *program
|
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) == __runner__) // conformed interfaces need not be declared, they are inferred
|
||||||
|
|
||||||
assert(bob.milesCompleted == 0)
|
assert(bob.milesCompleted == 0)
|
||||||
assert(rspec.executionCount == 0)
|
assert(rspec.executionCount == 0)
|
||||||
|
|
||||||
runTwice(bob) // bob fits the profile for a 'runner'
|
runTwice(bob) // bob fits the profile for a 'runner'
|
||||||
runTwice(rspec) // rspec also 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(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(rspec.executionCount == __int__) // rspec can run completely differently than bob, thanks to interfaces
|
||||||
}
|
}
|
||||||
|
|
||||||
// abstract interface and function that requires it
|
// abstract interface and function that requires it
|
||||||
|
|
||||||
type runner interface {
|
type runner interface {
|
||||||
run()
|
run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func runTwice(r runner) {
|
func runTwice(r runner) {
|
||||||
r.run()
|
r.run()
|
||||||
r.run()
|
r.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// concrete type implementing the interface
|
// concrete type implementing the interface
|
||||||
|
|
||||||
type human struct {
|
type human struct {
|
||||||
milesCompleted int
|
milesCompleted int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *human) run() {
|
func (self *human) run() {
|
||||||
self.milesCompleted++
|
self.milesCompleted++
|
||||||
}
|
}
|
||||||
|
|
||||||
// another concrete type implementing the interface
|
// another concrete type implementing the interface
|
||||||
|
|
||||||
type program struct {
|
type program struct {
|
||||||
executionCount int
|
executionCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *program) run() {
|
func (self *program) run() {
|
||||||
self.executionCount++
|
self.executionCount++
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutMaps() {
|
func aboutMaps() {
|
||||||
ages := map[string]int{
|
ages := map[string]int{
|
||||||
"bob": 10,
|
"bob": 10,
|
||||||
"joe": 20,
|
"joe": 20,
|
||||||
"dan": 30,
|
"dan": 30,
|
||||||
}
|
}
|
||||||
|
|
||||||
age := ages["bob"]
|
age := ages["bob"]
|
||||||
assert(age == __int__) // map syntax is warmly familiar
|
assert(age == __int__) // map syntax is warmly familiar
|
||||||
|
|
||||||
age, ok := ages["bob"]
|
age, ok := ages["bob"]
|
||||||
assert(ok == __bool__) // with a handy multiple-assignment variation
|
assert(ok == __bool__) // with a handy multiple-assignment variation
|
||||||
|
|
||||||
age, ok = ages["steven"]
|
age, ok = ages["steven"]
|
||||||
assert(age == __int__) // the zero value is used when absent
|
assert(age == __int__) // the zero value is used when absent
|
||||||
assert(ok == __boolean__) // though there are better ways to check for presence
|
assert(ok == __boolean__) // though there are better ways to check for presence
|
||||||
|
|
||||||
assert(len(ages) == __int__) // length is based on keys
|
assert(len(ages) == __int__) // length is based on keys
|
||||||
|
|
||||||
ages["bob"] = 99
|
ages["bob"] = 99
|
||||||
assert(ages["bob"] == __int__) // values can be changed for keys
|
assert(ages["bob"] == __int__) // values can be changed for keys
|
||||||
|
|
||||||
ages["steven"] = 77
|
ages["steven"] = 77
|
||||||
assert(ages[__string__] == 77) // new ones can be added
|
assert(ages[__string__] == 77) // new ones can be added
|
||||||
|
|
||||||
delete(ages, "steven")
|
delete(ages, "steven")
|
||||||
age, ok = ages["steven"]
|
age, ok = ages["steven"]
|
||||||
assert(ok == __boolean__) // key/value pairs can be removed
|
assert(ok == __boolean__) // key/value pairs can be removed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func divideFourBy(i int) int {
|
func divideFourBy(i int) int {
|
||||||
return 4 / i
|
return 4 / i
|
||||||
}
|
}
|
||||||
|
|
||||||
const __divisor__ = 0
|
const __divisor__ = 0
|
||||||
|
|
||||||
func aboutPanics() {
|
func aboutPanics() {
|
||||||
assert(__delete_me__) // panics are exceptional errors at runtime
|
assert(__delete_me__) // panics are exceptional errors at runtime
|
||||||
|
|
||||||
n := divideFourBy(__divisor__)
|
n := divideFourBy(__divisor__)
|
||||||
assert(n == 2) // panics are exceptional errors at runtime
|
assert(n == 2) // panics are exceptional errors at runtime
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutPointers() {
|
func aboutPointers() {
|
||||||
{
|
{
|
||||||
a := 3
|
a := 3
|
||||||
b := a // 'b' is a copy of 'a' (all assignments are copy-operations)
|
b := a // 'b' is a copy of 'a' (all assignments are copy-operations)
|
||||||
|
|
||||||
b++
|
b++
|
||||||
|
|
||||||
assert(a == __int__) // variables are independent of one another
|
assert(a == __int__) // variables are independent of one another
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
a := 3
|
a := 3
|
||||||
b := &a // 'b' is the address of 'a'
|
b := &a // 'b' is the address of 'a'
|
||||||
|
|
||||||
*b = *b + 2 // de-referencing 'b' means acting like a mutable copy 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
|
assert(a == __int__) // pointers seem complicated at first but are actually simple
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
increment := func(i int) {
|
increment := func(i int) {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
a := 3
|
a := 3
|
||||||
increment(a)
|
increment(a)
|
||||||
assert(a == __int__) // variables are always passed by value, and so a copy is made
|
assert(a == __int__) // variables are always passed by value, and so a copy is made
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
realIncrement := func(i *int) {
|
realIncrement := func(i *int) {
|
||||||
(*i)++
|
(*i)++
|
||||||
}
|
}
|
||||||
|
|
||||||
b := 3
|
b := 3
|
||||||
realIncrement(&b)
|
realIncrement(&b)
|
||||||
assert(b == __int__) // but passing a pointer allows others to mutate the value pointed to
|
assert(b == __int__) // but passing a pointer allows others to mutate the value pointed to
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutSlices() {
|
func aboutSlices() {
|
||||||
fruits := []string{"apple", "orange", "mango"}
|
fruits := []string{"apple", "orange", "mango"}
|
||||||
|
|
||||||
assert(fruits[0] == __string__) // slices seem like arrays
|
assert(fruits[0] == __string__) // slices seem like arrays
|
||||||
assert(len(fruits) == __int__) // in nearly all respects
|
assert(len(fruits) == __int__) // in nearly all respects
|
||||||
|
|
||||||
tasty_fruits := fruits[1:3] // we can even slice slices
|
tasty_fruits := fruits[1:3] // we can even slice slices
|
||||||
assert(tasty_fruits[0] == __string__) // slices of slices also share the underlying data
|
assert(tasty_fruits[0] == __string__) // slices of slices also share the underlying data
|
||||||
|
|
||||||
pregnancy_slots := []string{"baby", "baby", "lemon"}
|
pregnancy_slots := []string{"baby", "baby", "lemon"}
|
||||||
assert(cap(pregnancy_slots) == __int__) // the capacity is initially the length
|
assert(cap(pregnancy_slots) == __int__) // the capacity is initially the length
|
||||||
|
|
||||||
pregnancy_slots = append(pregnancy_slots, "baby!")
|
pregnancy_slots = append(pregnancy_slots, "baby!")
|
||||||
assert(len(pregnancy_slots) == __int__) // slices can be extended with append(), much like realloc in C
|
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(cap(pregnancy_slots) == __int__) // but with better optimizations
|
||||||
|
|
||||||
pregnancy_slots = append(pregnancy_slots, "another baby!?", "yet another, oh dear!", "they must be Catholic")
|
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(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(cap(pregnancy_slots) == __int__) // the capacity optimizations have a guessable algorithm
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,28 +3,28 @@ package go_koans
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func aboutStrings() {
|
func aboutStrings() {
|
||||||
assert("a"+__string__ == "abc") // string concatenation need not be difficult
|
assert("a"+__string__ == "abc") // string concatenation need not be difficult
|
||||||
assert(len("abc") == __int__) // and bounds are thoroughly checked
|
assert(len("abc") == __int__) // and bounds are thoroughly checked
|
||||||
|
|
||||||
assert("abc"[0] == __byte__) // their contents are reminiscent of C
|
assert("abc"[0] == __byte__) // their contents are reminiscent of C
|
||||||
|
|
||||||
assert("smith"[2:] == __string__) // slicing may omit the end point
|
assert("smith"[2:] == __string__) // slicing may omit the end point
|
||||||
assert("smith"[:4] == __string__) // or the beginning
|
assert("smith"[:4] == __string__) // or the beginning
|
||||||
assert("smith"[2:4] == __string__) // or neither
|
assert("smith"[2:4] == __string__) // or neither
|
||||||
assert("smith"[:] == __string__) // or both
|
assert("smith"[:] == __string__) // or both
|
||||||
|
|
||||||
assert("smith" == __string__) // they can be compared directly
|
assert("smith" == __string__) // they can be compared directly
|
||||||
assert("smith" < __string__) // i suppose maybe this could be useful.. someday
|
assert("smith" < __string__) // i suppose maybe this could be useful.. someday
|
||||||
|
|
||||||
bytes := []byte{'a', 'b', 'c'}
|
bytes := []byte{'a', 'b', 'c'}
|
||||||
assert(string(bytes) == __string__) // strings can be created from byte-slices
|
assert(string(bytes) == __string__) // strings can be created from byte-slices
|
||||||
|
|
||||||
bytes[0] = 'z'
|
bytes[0] = 'z'
|
||||||
assert(string(bytes) == __string__) // byte-slices can be mutated, although strings cannot
|
assert(string(bytes) == __string__) // 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", __string__) == "hello world") // our old friend sprintf returns
|
||||||
assert(fmt.Sprintf("hello \"%s\"", "world") == __string__) // quoting is familiar
|
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 %q", "world") == __string__) // 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) == __string__) // "the root of all evil" is actually a misquotation, by the way
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
func aboutStructs() {
|
func aboutStructs() {
|
||||||
var bob struct {
|
var bob struct {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
bob.name = "bob"
|
bob.name = "bob"
|
||||||
bob.age = 30
|
bob.age = 30
|
||||||
|
|
||||||
assert(bob.name == __string__) // structs are collections of named variables
|
assert(bob.name == __string__) // structs are collections of named variables
|
||||||
assert(bob.age == __int__) // each field has both setter and getter behavior
|
assert(bob.age == __int__) // each field has both setter and getter behavior
|
||||||
|
|
||||||
type person struct {
|
type person struct {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
|
|
||||||
var john person
|
var john person
|
||||||
john.name = "bob"
|
john.name = "bob"
|
||||||
john.age = __int__
|
john.age = __int__
|
||||||
|
|
||||||
assert(bob == john) // assuredly, bob is certainly not john.. yet
|
assert(bob == john) // assuredly, bob is certainly not john.. yet
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package go_koans
|
|||||||
type coolNumber int
|
type coolNumber int
|
||||||
|
|
||||||
func (cn coolNumber) multiplyByTwo() int {
|
func (cn coolNumber) multiplyByTwo() int {
|
||||||
return int(cn) * 2
|
return int(cn) * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func aboutTypes() {
|
func aboutTypes() {
|
||||||
i := coolNumber(4)
|
i := coolNumber(4)
|
||||||
assert(i == coolNumber(__int__)) // values can be converted between compatible types
|
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.multiplyByTwo() == __int__) // you can add methods on any type you define
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ package go_koans
|
|||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
func concatNames(sep string, names ...string) string {
|
func concatNames(sep string, names ...string) string {
|
||||||
return strings.Join(names, sep) // variadic parameters are really just slices
|
return strings.Join(names, sep) // variadic parameters are really just slices
|
||||||
}
|
}
|
||||||
|
|
||||||
func aboutVariadicFunctions() {
|
func aboutVariadicFunctions() {
|
||||||
{
|
{
|
||||||
str := concatNames(" ", "bob", "billy", "fred")
|
str := concatNames(" ", "bob", "billy", "fred")
|
||||||
assert(str == __string__) // several values can be passed to variadic parameters
|
assert(str == __string__) // several values can be passed to variadic parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
names := []string{"bob", "billy", "fred"}
|
names := []string{"bob", "billy", "fred"}
|
||||||
str := concatNames("-", names...)
|
str := concatNames("-", names...)
|
||||||
assert(str == __string__) // or a slice can be dotted in place of all of them
|
assert(str == __string__) // or a slice can be dotted in place of all of them
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,62 @@
|
|||||||
package go_koans
|
package go_koans
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
__string__ string = "impossibly lame value"
|
__string__ string = "impossibly lame value"
|
||||||
__int__ int = -1
|
__int__ int = -1
|
||||||
__positive_int__ int = 42
|
__positive_int__ int = 42
|
||||||
__byte__ byte = 255
|
__byte__ byte = 255
|
||||||
__bool__ bool = false // ugh
|
__bool__ bool = false // ugh
|
||||||
__boolean__ bool = true // oh well
|
__boolean__ bool = true // oh well
|
||||||
__float32__ float32 = -1.0
|
__float32__ float32 = -1.0
|
||||||
__delete_me__ bool = false
|
__delete_me__ bool = false
|
||||||
)
|
)
|
||||||
|
|
||||||
var __runner__ runner = nil
|
var __runner__ runner = nil
|
||||||
|
|
||||||
func TestKoans(t *testing.T) {
|
func TestKoans(t *testing.T) {
|
||||||
aboutBasics()
|
aboutBasics()
|
||||||
aboutStrings()
|
aboutStrings()
|
||||||
aboutArrays()
|
aboutArrays()
|
||||||
aboutSlices()
|
aboutSlices()
|
||||||
aboutTypes()
|
aboutTypes()
|
||||||
aboutControlFlow()
|
aboutControlFlow()
|
||||||
aboutEnumeration()
|
aboutEnumeration()
|
||||||
aboutAnonymousFunctions()
|
aboutAnonymousFunctions()
|
||||||
aboutVariadicFunctions()
|
aboutVariadicFunctions()
|
||||||
aboutFiles()
|
aboutFiles()
|
||||||
aboutInterfaces()
|
aboutInterfaces()
|
||||||
aboutCommonInterfaces()
|
aboutCommonInterfaces()
|
||||||
aboutMaps()
|
aboutMaps()
|
||||||
aboutPointers()
|
aboutPointers()
|
||||||
aboutStructs()
|
aboutStructs()
|
||||||
aboutAllocation()
|
aboutAllocation()
|
||||||
aboutChannels()
|
aboutChannels()
|
||||||
aboutConcurrency()
|
aboutConcurrency()
|
||||||
aboutPanics()
|
aboutPanics()
|
||||||
|
|
||||||
fmt.Printf("\n%c[32;1mYou won life. Good job.\n\n", 27)
|
fmt.Printf("\n%c[32;1mYou won life. Good job.\n\n", 27)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assert(o bool) {
|
func assert(o bool) {
|
||||||
if !o {
|
if !o {
|
||||||
fmt.Printf("\n%c[35m%s%c[0m\n\n", 27, __getRecentLine(), 27)
|
fmt.Printf("\n%c[35m%s%c[0m\n\n", 27, __getRecentLine(), 27)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func __getRecentLine() string {
|
func __getRecentLine() string {
|
||||||
_, file, line, _ := runtime.Caller(2)
|
_, file, line, _ := runtime.Caller(2)
|
||||||
buf, _ := ioutil.ReadFile(file)
|
buf, _ := ioutil.ReadFile(file)
|
||||||
code := strings.TrimSpace(strings.Split(string(buf), "\n")[line-1])
|
code := strings.TrimSpace(strings.Split(string(buf), "\n")[line-1])
|
||||||
return fmt.Sprintf("%v:%d\n%s", path.Base(file), line, code)
|
return fmt.Sprintf("%v:%d\n%s", path.Base(file), line, code)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user