Merge pull request #676 from heyalexej/patch-1

fix import of io/ioutil, run gofmt
This commit is contained in:
Levi Bostian 2014-07-16 11:07:42 -05:00
commit 57c384420e

View File

@ -9,6 +9,7 @@ contributors:
- ["Jesse Johnson", "https://github.com/holocronweaver"] - ["Jesse Johnson", "https://github.com/holocronweaver"]
- ["Quint Guvernator", "https://github.com/qguv"] - ["Quint Guvernator", "https://github.com/qguv"]
- ["Jose Donizetti", "https://github.com/josedonizetti"] - ["Jose Donizetti", "https://github.com/josedonizetti"]
- ["Alexej Friesen", "https://github.com/heyalexej"]
--- ---
Go was created out of the need to get work done. It's not the latest trend Go was created out of the need to get work done. It's not the latest trend
@ -33,87 +34,88 @@ package main
// Import declaration declares library packages referenced in this file. // Import declaration declares library packages referenced in this file.
import ( import (
"fmt" // A package in the Go standard library. "fmt" // A package in the Go standard library.
"net/http" // Yes, a web server! "io/ioutil" // Implements some I/O utility functions.
"strconv" // String conversions. m "math" // Math library with local alias m.
m "math" // Math library with local alias m. "net/http" // Yes, a web server!
"strconv" // String conversions.
) )
// A function definition. Main is special. It is the entry point for the // A function definition. Main is special. It is the entry point for the
// executable program. Love it or hate it, Go uses brace brackets. // executable program. Love it or hate it, Go uses brace brackets.
func main() { func main() {
// Println outputs a line to stdout. // Println outputs a line to stdout.
// Qualify it with the package name, fmt. // Qualify it with the package name, fmt.
fmt.Println("Hello world!") fmt.Println("Hello world!")
// Call another function within this package. // Call another function within this package.
beyondHello() beyondHello()
} }
// Functions have parameters in parentheses. // Functions have parameters in parentheses.
// If there are no parameters, empty parentheses are still required. // If there are no parameters, empty parentheses are still required.
func beyondHello() { func beyondHello() {
var x int // Variable declaration. Variables must be declared before use. var x int // Variable declaration. Variables must be declared before use.
x = 3 // Variable assignment. x = 3 // Variable assignment.
// "Short" declarations use := to infer the type, declare, and assign. // "Short" declarations use := to infer the type, declare, and assign.
y := 4 y := 4
sum, prod := learnMultiple(x, y) // Function returns two values. sum, prod := learnMultiple(x, y) // Function returns two values.
fmt.Println("sum:", sum, "prod:", prod) // Simple output. fmt.Println("sum:", sum, "prod:", prod) // Simple output.
learnTypes() // < y minutes, learn more! learnTypes() // < y minutes, learn more!
} }
// Functions can have parameters and (multiple!) return values. // Functions can have parameters and (multiple!) return values.
func learnMultiple(x, y int) (sum, prod int) { func learnMultiple(x, y int) (sum, prod int) {
return x + y, x * y // Return two values. return x + y, x * y // Return two values.
} }
// Some built-in types and literals. // Some built-in types and literals.
func learnTypes() { func learnTypes() {
// Short declaration usually gives you what you want. // Short declaration usually gives you what you want.
s := "Learn Go!" // string type. s := "Learn Go!" // string type.
s2 := `A "raw" string literal s2 := `A "raw" string literal
can include line breaks.` // Same string type. can include line breaks.` // Same string type.
// Non-ASCII literal. Go source is UTF-8. // Non-ASCII literal. Go source is UTF-8.
g := 'Σ' // rune type, an alias for uint32, holds a unicode code point. g := 'Σ' // rune type, an alias for uint32, holds a unicode code point.
f := 3.14195 // float64, an IEEE-754 64-bit floating point number. f := 3.14195 // float64, an IEEE-754 64-bit floating point number.
c := 3 + 4i // complex128, represented internally with two float64's. c := 3 + 4i // complex128, represented internally with two float64's.
// Var syntax with an initializers. // Var syntax with an initializers.
var u uint = 7 // Unsigned, but implementation dependent size as with int. var u uint = 7 // Unsigned, but implementation dependent size as with int.
var pi float32 = 22. / 7 var pi float32 = 22. / 7
// Conversion syntax with a short declaration. // Conversion syntax with a short declaration.
n := byte('\n') // byte is an alias for uint8. n := byte('\n') // byte is an alias for uint8.
// Arrays have size fixed at compile time. // Arrays have size fixed at compile time.
var a4 [4]int // An array of 4 ints, initialized to all 0. var a4 [4]int // An array of 4 ints, initialized to all 0.
a3 := [...]int{3, 1, 5} // An array of 3 ints, initialized as shown. a3 := [...]int{3, 1, 5} // An array of 3 ints, initialized as shown.
// Slices have dynamic size. Arrays and slices each have advantages // Slices have dynamic size. Arrays and slices each have advantages
// but use cases for slices are much more common. // but use cases for slices are much more common.
s3 := []int{4, 5, 9} // Compare to a3. No ellipsis here. s3 := []int{4, 5, 9} // Compare to a3. No ellipsis here.
s4 := make([]int, 4) // Allocates slice of 4 ints, initialized to all 0. s4 := make([]int, 4) // Allocates slice of 4 ints, initialized to all 0.
var d2 [][]float64 // Declaration only, nothing allocated here. var d2 [][]float64 // Declaration only, nothing allocated here.
bs := []byte("a slice") // Type conversion syntax. bs := []byte("a slice") // Type conversion syntax.
p, q := learnMemory() // Declares p, q to be type pointer to int. p, q := learnMemory() // Declares p, q to be type pointer to int.
fmt.Println(*p, *q) // * follows a pointer. This prints two ints. fmt.Println(*p, *q) // * follows a pointer. This prints two ints.
// Maps are a dynamically growable associative array type, like the // Maps are a dynamically growable associative array type, like the
// hash or dictionary types of some other languages. // hash or dictionary types of some other languages.
m := map[string]int{"three": 3, "four": 4} m := map[string]int{"three": 3, "four": 4}
m["one"] = 1 m["one"] = 1
// Unused variables are an error in Go. // Unused variables are an error in Go.
// The underbar lets you "use" a variable but discard its value. // The underbar lets you "use" a variable but discard its value.
_, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs _, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs
// Output of course counts as using a variable. // Output of course counts as using a variable.
fmt.Println(s, c, a4, s3, d2, m) fmt.Println(s, c, a4, s3, d2, m)
learnFlowControl() // Back in the flow. learnFlowControl() // Back in the flow.
} }
// It is possible, unlike in many other languages for functions in go // It is possible, unlike in many other languages for functions in go
@ -122,250 +124,249 @@ can include line breaks.` // Same string type.
// allows us to easily return from multiple points in a function as well as to // allows us to easily return from multiple points in a function as well as to
// only use the return keyword, without anything further. // only use the return keyword, without anything further.
func learnNamedReturns(x, y int) (z int) { func learnNamedReturns(x, y int) (z int) {
z = x * y z = x * y
return // z is implicit here, because we named it earlier. return // z is implicit here, because we named it earlier.
} }
// Go is fully garbage collected. It has pointers but no pointer arithmetic. // Go is fully garbage collected. It has pointers but no pointer arithmetic.
// You can make a mistake with a nil pointer, but not by incrementing a pointer. // You can make a mistake with a nil pointer, but not by incrementing a pointer.
func learnMemory() (p, q *int) { func learnMemory() (p, q *int) {
// Named return values p and q have type pointer to int. // Named return values p and q have type pointer to int.
p = new(int) // Built-in function new allocates memory. p = new(int) // Built-in function new allocates memory.
// The allocated int is initialized to 0, p is no longer nil. // The allocated int is initialized to 0, p is no longer nil.
s := make([]int, 20) // Allocate 20 ints as a single block of memory. s := make([]int, 20) // Allocate 20 ints as a single block of memory.
s[3] = 7 // Assign one of them. s[3] = 7 // Assign one of them.
r := -2 // Declare another local variable. r := -2 // Declare another local variable.
return &s[3], &r // & takes the address of an object. return &s[3], &r // & takes the address of an object.
} }
func expensiveComputation() float64 { func expensiveComputation() float64 {
return m.Exp(10) return m.Exp(10)
} }
func learnFlowControl() { func learnFlowControl() {
// If statements require brace brackets, and do not require parens. // If statements require brace brackets, and do not require parens.
if true { if true {
fmt.Println("told ya") fmt.Println("told ya")
} }
// Formatting is standardized by the command line command "go fmt." // Formatting is standardized by the command line command "go fmt."
if false { if false {
// Pout. // Pout.
} else { } else {
// Gloat. // Gloat.
} }
// Use switch in preference to chained if statements. // Use switch in preference to chained if statements.
x := 42.0 x := 42.0
switch x { switch x {
case 0: case 0:
case 1: case 1:
case 42: case 42:
// Cases don't "fall through". // Cases don't "fall through".
case 43: case 43:
// Unreached. // Unreached.
} }
// Like if, for doesn't use parens either. // Like if, for doesn't use parens either.
// Variables declared in for and if are local to their scope. // Variables declared in for and if are local to their scope.
for x := 0; x < 3; x++ { // ++ is a statement. for x := 0; x < 3; x++ { // ++ is a statement.
fmt.Println("iteration", x) fmt.Println("iteration", x)
} }
// x == 42 here. // x == 42 here.
// For is the only loop statement in Go, but it has alternate forms. // For is the only loop statement in Go, but it has alternate forms.
for { // Infinite loop. for { // Infinite loop.
break // Just kidding. break // Just kidding.
continue // Unreached. continue // Unreached.
} }
// As with for, := in an if statement means to declare and assign y first, // As with for, := in an if statement means to declare and assign
// then test y > x. // y first, then test y > x.
if y := expensiveComputation(); y > x { if y := expensiveComputation(); y > x {
x = y x = y
} }
// Function literals are closures. // Function literals are closures.
xBig := func() bool { xBig := func() bool {
return x > 10000 // References x declared above switch statement. return x > 10000 // References x declared above switch statement.
} }
fmt.Println("xBig:", xBig()) // true (we last assigned e^10 to x). fmt.Println("xBig:", xBig()) // true (we last assigned e^10 to x).
x = 1.3e3 // This makes x == 1300 x = 1.3e3 // This makes x == 1300
fmt.Println("xBig:", xBig()) // false now. fmt.Println("xBig:", xBig()) // false now.
// What's more is function literals may be defined and called inline, // What's more is function literals may be defined and called inline,
// acting as an argument to function, as long as: // acting as an argument to function, as long as:
// a) function literal is called immediately (), // a) function literal is called immediately (),
// b) result type matches expected type of argument. // b) result type matches expected type of argument.
fmt.Println("Add + double two numbers: ", fmt.Println("Add + double two numbers: ",
func(a, b int) int { func(a, b int) int {
return (a + b) * 2 return (a + b) * 2
}(10, 2)) // Called with args 10 and 2 }(10, 2)) // Called with args 10 and 2
// => Add + double two numbers: 24 // => Add + double two numbers: 24
// When you need it, you'll love it. // When you need it, you'll love it.
goto love goto love
love: love:
learnFunctionFactory() // func returning func is fun(3)(3) learnFunctionFactory() // func returning func is fun(3)(3)
learnDefer() // A quick detour to an important keyword. learnDefer() // A quick detour to an important keyword.
learnInterfaces() // Good stuff coming up! learnInterfaces() // Good stuff coming up!
} }
func learnFunctionFactory() { func learnFunctionFactory() {
// Next two are equivalent, with second being more practical // Next two are equivalent, with second being more practical
fmt.Println(sentenceFactory("summer")("A beautiful", "day!")) fmt.Println(sentenceFactory("summer")("A beautiful", "day!"))
d := sentenceFactory("summer") d := sentenceFactory("summer")
fmt.Println(d("A beautiful", "day!")) fmt.Println(d("A beautiful", "day!"))
fmt.Println(d("A lazy", "afternoon!")) fmt.Println(d("A lazy", "afternoon!"))
} }
// Decorators are common in other languages. Same can be done in Go // Decorators are common in other languages. Same can be done in Go
// with function literals that accept arguments. // with function literals that accept arguments.
func sentenceFactory(mystring string) func(before, after string) string { func sentenceFactory(mystring string) func(before, after string) string {
return func(before, after string) string { return func(before, after string) string {
return fmt.Sprintf("%s %s %s", before, mystring, after) // new string return fmt.Sprintf("%s %s %s", before, mystring, after) // new string
} }
} }
func learnDefer() (ok bool) { func learnDefer() (ok bool) {
// Deferred statements are executed just before the function returns. // Deferred statements are executed just before the function returns.
defer fmt.Println("deferred statements execute in reverse (LIFO) order.") defer fmt.Println("deferred statements execute in reverse (LIFO) order.")
defer fmt.Println("\nThis line is being printed first because") defer fmt.Println("\nThis line is being printed first because")
// Defer is commonly used to close a file, so the function closing the file // Defer is commonly used to close a file, so the function closing the
// stays close to the function opening the file // file stays close to the function opening the file.
return true return true
} }
// Define Stringer as an interface type with one method, String. // Define Stringer as an interface type with one method, String.
type Stringer interface { type Stringer interface {
String() string String() string
} }
// Define pair as a struct with two fields, ints named x and y. // Define pair as a struct with two fields, ints named x and y.
type pair struct { type pair struct {
x, y int x, y int
} }
// Define a method on type pair. Pair now implements Stringer. // Define a method on type pair. Pair now implements Stringer.
func (p pair) String() string { // p is called the "receiver" func (p pair) String() string { // p is called the "receiver"
// Sprintf is another public function in package fmt. // Sprintf is another public function in package fmt.
// Dot syntax references fields of p. // Dot syntax references fields of p.
return fmt.Sprintf("(%d, %d)", p.x, p.y) return fmt.Sprintf("(%d, %d)", p.x, p.y)
} }
func learnInterfaces() { func learnInterfaces() {
// Brace syntax is a "struct literal." It evaluates to an initialized // Brace syntax is a "struct literal." It evaluates to an initialized
// struct. The := syntax declares and initializes p to this struct. // struct. The := syntax declares and initializes p to this struct.
p := pair{3, 4} p := pair{3, 4}
fmt.Println(p.String()) // Call String method of p, of type pair. fmt.Println(p.String()) // Call String method of p, of type pair.
var i Stringer // Declare i of interface type Stringer. var i Stringer // Declare i of interface type Stringer.
i = p // Valid because pair implements Stringer i = p // Valid because pair implements Stringer
// Call String method of i, of type Stringer. Output same as above. // Call String method of i, of type Stringer. Output same as above.
fmt.Println(i.String()) fmt.Println(i.String())
// Functions in the fmt package call the String method to ask an object // Functions in the fmt package call the String method to ask an object
// for a printable representation of itself. // for a printable representation of itself.
fmt.Println(p) // Output same as above. Println calls String method. fmt.Println(p) // Output same as above. Println calls String method.
fmt.Println(i) // Output same as above. fmt.Println(i) // Output same as above.
learnVariadicParams("great", "learning", "here!") learnVariadicParams("great", "learning", "here!")
} }
// Functions can have variadic parameters. // Functions can have variadic parameters.
func learnVariadicParams(myStrings ...interface{}) { func learnVariadicParams(myStrings ...interface{}) {
// Iterate each value of the variadic. // Iterate each value of the variadic.
// The underbar here is ignoring the index argument of the array. // The underbar here is ignoring the index argument of the array.
for _, param := range myStrings { for _, param := range myStrings {
fmt.Println("param:", param) fmt.Println("param:", param)
} }
// Pass variadic value as a variadic parameter. // Pass variadic value as a variadic parameter.
fmt.Println("params:", fmt.Sprintln(myStrings...)) fmt.Println("params:", fmt.Sprintln(myStrings...))
learnErrorHandling() learnErrorHandling()
} }
func learnErrorHandling() { func learnErrorHandling() {
// ", ok" idiom used to tell if something worked or not. // ", ok" idiom used to tell if something worked or not.
m := map[int]string{3: "three", 4: "four"} m := map[int]string{3: "three", 4: "four"}
if x, ok := m[1]; !ok { // ok will be false because 1 is not in the map. if x, ok := m[1]; !ok { // ok will be false because 1 is not in the map.
fmt.Println("no one there") fmt.Println("no one there")
} else { } else {
fmt.Print(x) // x would be the value, if it were in the map. fmt.Print(x) // x would be the value, if it were in the map.
} }
// An error value communicates not just "ok" but more about the problem. // An error value communicates not just "ok" but more about the problem.
if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value
// prints 'strconv.ParseInt: parsing "non-int": invalid syntax' // prints 'strconv.ParseInt: parsing "non-int": invalid syntax'
fmt.Println(err) fmt.Println(err)
} }
// We'll revisit interfaces a little later. Meanwhile, // We'll revisit interfaces a little later. Meanwhile,
learnConcurrency() learnConcurrency()
} }
// c is a channel, a concurrency-safe communication object. // c is a channel, a concurrency-safe communication object.
func inc(i int, c chan int) { func inc(i int, c chan int) {
c <- i + 1 // <- is the "send" operator when a channel appears on the left. c <- i + 1 // <- is the "send" operator when a channel appears on the left.
} }
// We'll use inc to increment some numbers concurrently. // We'll use inc to increment some numbers concurrently.
func learnConcurrency() { func learnConcurrency() {
// Same make function used earlier to make a slice. Make allocates and // Same make function used earlier to make a slice. Make allocates and
// initializes slices, maps, and channels. // initializes slices, maps, and channels.
c := make(chan int) c := make(chan int)
// Start three concurrent goroutines. Numbers will be incremented // Start three concurrent goroutines. Numbers will be incremented
// concurrently, perhaps in parallel if the machine is capable and // concurrently, perhaps in parallel if the machine is capable and
// properly configured. All three send to the same channel. // properly configured. All three send to the same channel.
go inc(0, c) // go is a statement that starts a new goroutine. go inc(0, c) // go is a statement that starts a new goroutine.
go inc(10, c) go inc(10, c)
go inc(-805, c) go inc(-805, c)
// Read three results from the channel and print them out. // Read three results from the channel and print them out.
// There is no telling in what order the results will arrive! // There is no telling in what order the results will arrive!
fmt.Println(<-c, <-c, <-c) // channel on right, <- is "receive" operator. fmt.Println(<-c, <-c, <-c) // channel on right, <- is "receive" operator.
cs := make(chan string) // Another channel, this one handles strings. cs := make(chan string) // Another channel, this one handles strings.
ccs := make(chan chan string) // A channel of string channels. ccs := make(chan chan string) // A channel of string channels.
go func() { c <- 84 }() // Start a new goroutine just to send a value. go func() { c <- 84 }() // Start a new goroutine just to send a value.
go func() { cs <- "wordy" }() // Again, for cs this time. go func() { cs <- "wordy" }() // Again, for cs this time.
// Select has syntax like a switch statement but each case involves // Select has syntax like a switch statement but each case involves
// a channel operation. It selects a case at random out of the cases // a channel operation. It selects a case at random out of the cases
// that are ready to communicate. // that are ready to communicate.
select { select {
case i := <-c: // The value received can be assigned to a variable, case i := <-c: // The value received can be assigned to a variable,
fmt.Printf("it's a %T", i) fmt.Printf("it's a %T", i)
case <-cs: // or the value received can be discarded. case <-cs: // or the value received can be discarded.
fmt.Println("it's a string") fmt.Println("it's a string")
case <-ccs: // Empty channel, not ready for communication. case <-ccs: // Empty channel, not ready for communication.
fmt.Println("didn't happen.") fmt.Println("didn't happen.")
} }
// At this point a value was taken from either c or cs. One of the two // At this point a value was taken from either c or cs. One of the two
// goroutines started above has completed, the other will remain blocked. // goroutines started above has completed, the other will remain blocked.
learnWebProgramming() // Go does it. You want to do it too. learnWebProgramming() // Go does it. You want to do it too.
} }
// A single function from package http starts a web server. // A single function from package http starts a web server.
func learnWebProgramming() { func learnWebProgramming() {
// First parameter of ListenAndServe is TCP address to listen to. // First parameter of ListenAndServe is TCP address to listen to.
// Second parameter is an interface, specifically http.Handler. // Second parameter is an interface, specifically http.Handler.
go func() { go func() {
err := http.ListenAndServe(":8080", pair{}) err := http.ListenAndServe(":8080", pair{})
fmt.Println(err) // don't ignore errors fmt.Println(err) // don't ignore errors
}() }()
requestServer(); requestServer()
} }
// Make pair an http.Handler by implementing its only method, ServeHTTP. // Make pair an http.Handler by implementing its only method, ServeHTTP.
func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Serve data with a method of http.ResponseWriter. // Serve data with a method of http.ResponseWriter.
w.Write([]byte("You learned Go in Y minutes!")) w.Write([]byte("You learned Go in Y minutes!"))
} }
func requestServer() { func requestServer() {
resp, err := http.Get("http://localhost:8080") resp, err := http.Get("http://localhost:8080")
fmt.Println(err) fmt.Println(err)
defer resp.Body.Close() defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
fmt.Printf("\nWebserver said: `%s`", string(body)) fmt.Printf("\nWebserver said: `%s`", string(body))
} }
``` ```