Start translation to brazilian portuguese

This commit is contained in:
Gustavo Kuklinski
2015-07-05 22:56:01 -03:00
parent 3219cc6f3b
commit 5504747def
273 changed files with 16240 additions and 0 deletions

7
pt-br/code/readme.md Normal file
View File

@@ -0,0 +1,7 @@
## Workspace setup.
To avoid workspace issues and be able to develop from any folder within this path,
set the environment variable `GOPATH` to the path of this directory.
More info:
- [GOPATH documentation](http://golang.org/doc/code.html#GOPATH)

View File

@@ -0,0 +1,14 @@
// Example code for Chapter 1.2 from "Build Web Application with Golang"
// Purpose: Run this file to check if your workspace is setup correctly.
// To run, navigate to the current directory in a console and type `go run main.go`
// If the text "Hello World" isn't shown, then setup your workspace again.
package main
import (
"fmt"
"mymath"
)
func main() {
fmt.Printf("Hello, world. Sqrt(2) = %v\n", mymath.Sqrt(2))
}

View File

@@ -0,0 +1,11 @@
// Example code for Chapter ? from "Build Web Application with Golang"
// Purpose: Hello world example demonstrating UTF-8 support.
// To run in the console, type `go run main.go`
// You're missing language fonts, if you're seeing squares or question marks.
package main
import "fmt"
func main() {
fmt.Printf("Hello, world or 你好,世界 or καλημ ́ρα κóσμ or こんにちは世界\n")
}

View File

@@ -0,0 +1,277 @@
// Example code for Chapter 2.2 from "Build Web Application with Golang"
// Purpose: Goes over the assignment and manipulation of basic data types.
package main
import (
"errors"
"fmt"
)
// constants
const Pi = 3.1415926
// booleans default to `false`
var isActive bool // global variable
var enabled, disabled = true, false // omit type of variables
// grouped definitions
const (
i = 1e4
MaxThread = 10
prefix = "astaxie_"
)
var (
frenchHello string // basic form to define string
emptyString string = "" // define a string with empty string
)
func show_multiple_assignments() {
fmt.Println("show_multiple_assignments()")
var v1 int = 42
// Define three variables with type "int", and initialize their values.
// vname1 is v1, vname2 is v2, vname3 is v3
var v2, v3 int = 2, 3
// `:=` only works in functions
// `:=` is the short way of declaring variables without
// specifying the type and using the keyboard `var`.
vname1, vname2, vname3 := v1, v2, v3
// `_` disregards the returned value.
_, b := 34, 35
fmt.Printf("vname1 = %v, vname2 = %v, vname3 = %v\n", vname1, vname2, vname3)
fmt.Printf("v1 = %v, v2 = %v, v3 = %v\n", v1, v2, v3)
fmt.Println("b =", b)
}
func show_bool() {
fmt.Println("show_bool()")
var available bool // local variable
valid := false // Shorthand assignment
available = true // assign value to variable
fmt.Printf("valid = %v, !valid = %v\n", valid, !valid)
fmt.Printf("available = %v\n", available)
}
func show_different_types() {
fmt.Println("show_different_types()")
var (
unicodeChar rune
a int8
b int16
c int32
d int64
e byte
f uint8
g int16
h uint32
i uint64
)
var cmplx complex64 = 5 + 5i
fmt.Println("Default values for int types")
fmt.Println(unicodeChar, a, b, c, d, e, f, g, h, i)
fmt.Printf("Value is: %v\n", cmplx)
}
func show_strings() {
fmt.Println("show_strings()")
no, yes, maybe := "no", "yes", "maybe" // brief statement
japaneseHello := "Ohaiyou"
frenchHello = "Bonjour" // basic form of assign values
fmt.Println("Random strings")
fmt.Println(frenchHello, japaneseHello, no, yes, maybe)
// The backtick, `, will not escape any character in a string
fmt.Println(`This
is on
multiple lines`)
}
func show_string_manipulation() {
fmt.Println("show_string_manipulation()")
var s string = "hello"
//You can't do this with strings
//s[0] = 'c'
s = "hello"
c := []byte(s) // convert string to []byte type
c[0] = 'c'
s2 := string(c) // convert back to string type
m := " world"
a := s + m
d := "c" + s[1:] // you cannot change string values by index, but you can get values instead.
fmt.Printf("%s\n", d)
fmt.Printf("s = %s, c = %v\n", s, c)
fmt.Printf("s2 = %s\n", s2)
fmt.Printf("combined strings\na = %s, d = %s\n", a, d)
}
func show_errors() {
fmt.Println("show_errors()")
err := errors.New("Example error message\n")
if err != nil {
fmt.Print(err)
}
}
func show_iota() {
fmt.Println("show_iota()")
const (
x = iota // x == 0
y = iota // y == 1
z = iota // z == 2
w // If there is no expression after constants name,
// it uses the last expression, so here is saying w = iota implicitly.
// Therefore w == 3, and y and x both can omit "= iota" as well.
)
const v = iota // once iota meets keyword `const`, it resets to `0`, so v = 0.
const (
e, f, g = iota, iota, iota // e=0,f=0,g=0 values of iota are same in one line.
)
fmt.Printf("x = %v, y = %v, z = %v, w = %v\n", x, y, z, w)
fmt.Printf("v = %v\n", v)
fmt.Printf("e = %v, f = %v, g = %v\n", e, f, g)
}
// Functions and variables starting with a capital letter are public to other packages.
// Everything else is private.
func This_is_public() {}
func this_is_private() {}
func set_default_values() {
// default values for the types.
const (
a int = 0
b int8 = 0
c int32 = 0
d int64 = 0
e uint = 0x0
f rune = 0 // the actual type of rune is int32
g byte = 0x0 // the actual type of byte is uint8
h float32 = 0 // length is 4 byte
i float64 = 0 //length is 8 byte
j bool = false
k string = ""
)
}
func show_arrays() {
fmt.Println("show_arrays()")
var arr [10]int // an array of type int
arr[0] = 42 // array is 0-based
arr[1] = 13 // assign value to element
a := [3]int{1, 2, 3} // define a int array with 3 elements
b := [10]int{1, 2, 3}
// define a int array with 10 elements,
// and first three are assigned, rest of them use default value 0.
c := [...]int{4, 5, 6} // use `…` replace with number of length, Go will calculate it for you.
// define a two-dimensional array with 2 elements, and each element has 4 elements.
doubleArray := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}}
// You can write about declaration in a shorter way.
easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}
fmt.Println("arr =", arr)
fmt.Printf("The first element is %d\n", arr[0]) // get element value, it returns 42
fmt.Printf("The last element is %d\n", arr[9])
//it returns default value of 10th element in this array, which is 0 in this case.
fmt.Println("array a =", a)
fmt.Println("array b =", b)
fmt.Println("array c =", c)
fmt.Println("array doubleArray =", doubleArray)
fmt.Println("array easyArray =", easyArray)
}
func show_slices() {
fmt.Println("show_slices()")
// define a slice with 10 elements which types are byte
var ar = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// define two slices with type []byte
var a, b []byte
// a points to elements from 3rd to 5th in array ar.
a = ar[2:5]
// now a has elements ar[2]、ar[3] and ar[4]
// b is another slice of array ar
b = ar[3:5]
// now b has elements ar[3] and ar[4]
// define an array
var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// define two slices
var aSlice, bSlice []byte
// some convenient operations
aSlice = array[:3] // equals to aSlice = array[0:3] aSlice has elements a,b,c
aSlice = array[5:] // equals to aSlice = array[5:10] aSlice has elements f,g,h,i,j
aSlice = array[:] // equals to aSlice = array[0:10] aSlice has all elements
// slice from slice
aSlice = array[3:7] // aSlice has elements d,e,f,glen=4cap=7
bSlice = aSlice[1:3] // bSlice contains aSlice[1], aSlice[2], so it has elements e,f
bSlice = aSlice[:3] // bSlice contains aSlice[0], aSlice[1], aSlice[2], so it has d,e,f
bSlice = aSlice[0:5] // slcie could be expanded in range of cap, now bSlice contains d,e,f,g,h
bSlice = aSlice[:] // bSlice has same elements as aSlice does, which are d,e,f,g
fmt.Println("slice ar =", ar)
fmt.Println("slice a =", a)
fmt.Println("slice b =", b)
fmt.Println("array =", array)
fmt.Println("slice aSlice =", aSlice)
fmt.Println("slice bSlice =", bSlice)
fmt.Println("len(bSlice) =", len(bSlice))
}
func show_map() {
fmt.Println("show_map()")
// use string as key type, int as value type, and you have to use `make` initialize it.
var numbers map[string]int
// another way to define map
numbers = make(map[string]int)
numbers["one"] = 1 // assign value by key
numbers["ten"] = 10
numbers["three"] = 3
// Initialize a map
rating := map[string]float32{"C": 5, "Go": 4.5, "Python": 4.5, "C++": 2}
fmt.Println("map numbers =", numbers)
fmt.Println("The third number is: ", numbers["three"]) // get values
// It prints: The third number is: 3
// map has two return values. For second value, if the key doesn't existok is falsetrue otherwise.
csharpRating, ok := rating["C#"]
if ok {
fmt.Println("C# is in the map and its rating is ", csharpRating)
} else {
fmt.Println("We have no rating associated with C# in the map")
}
delete(rating, "C") // delete element with key "c"
fmt.Printf("map rating = %#v\n", rating)
}
func main() {
show_multiple_assignments()
show_bool()
show_different_types()
show_strings()
show_string_manipulation()
show_errors()
show_iota()
set_default_values()
show_arrays()
show_slices()
show_map()
}

View File

@@ -0,0 +1,8 @@
// Example code for Chapter 2.2 from "Build Web Application with Golang"
// Purpose: Try to fix this program.
// From the console, type `go run main.go`
package main
func main() {
var i int
}

View File

@@ -0,0 +1,26 @@
// Example code for Chapter 2.3 from "Build Web Application with Golang"
// Purpose: Creating a basic function
package main
import "fmt"
// return greater value between a and b
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
x := 3
y := 4
z := 5
max_xy := max(x, y) // call function max(x, y)
max_xz := max(x, z) // call function max(x, z)
fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
fmt.Printf("max(%d, %d) = %d\n", y, z, max(y, z)) // call function here
}

View File

@@ -0,0 +1,14 @@
// As of Google go 1.1.2, `println()` and `print()` are hidden functions included from the runtime package.
// However it's encouraged to use the print functions from the `fmt` package.
package main
import "fmt"
func f() {
fmt.Println("First")
print("Second ")
println(" Third")
}
func main() {
f()
}

View File

@@ -0,0 +1,26 @@
// Example code for Chapter 2.3 from "Build Web Application with Golang"
// Purpose: Shows different ways of importing a package.
// Note: For the package `only_call_init`, we reference the path from the
// base directory of `$GOPATH/src`. The reason being Golang discourage
// the use of relative paths when import packages.
// BAD: "./only_call_init"
// GOOD: "apps/ch.2.3/import_packages/only_call_init"
package main
import (
// `_` will only call init() inside the package only_call_init
_ "apps/ch.2.3/import_packages/only_call_init"
f "fmt" // import the package as `f`
. "math" // makes the public methods and constants global
"mymath" // custom package located at $GOPATH/src/
"os" // normal import of a standard package
"text/template" // the package takes the name of last folder path, `template`
)
func main() {
f.Println("mymath.Sqrt(4) =", mymath.Sqrt(4))
f.Println("E =", E) // references math.E
t, _ := template.New("test").Parse("Pi^2 = {{.}}")
t.Execute(os.Stdout, Pow(Pi, 2))
}

View File

@@ -0,0 +1,7 @@
package only_call_init
import "fmt"
func init() {
fmt.Println("only_call_init.init() was called.")
}

View File

@@ -0,0 +1,142 @@
// Example code for Chapter 2.3 from "Build Web Application with Golang"
// Purpose: Goes over if, else, switch conditions, loops and defer.
package main
import "fmt"
func computedValue() int {
return 1
}
func show_if() {
fmt.Println("\n#show_if()")
x := computedValue()
integer := 23
fmt.Println("x =", x)
fmt.Println("integer =", integer)
if x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is less than 10")
}
if integer == 3 {
fmt.Println("The integer is equal to 3")
} else if integer < 3 {
fmt.Println("The integer is less than 3")
} else {
fmt.Println("The integer is greater than 3")
}
}
func show_if_var() {
fmt.Println("\n#show_if_var()")
// initialize x, then check if x greater than
if x := computedValue(); x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is less than 10")
}
// the following code will not compile, since `x` is only accessable with the if/else block
// fmt.Println(x)
}
func show_goto() {
fmt.Println("\n#show_goto()")
// The call to the label switches the goroutine it seems.
i := 0
Here: // label ends with ":"
fmt.Println(i)
i++
if i < 10 {
goto Here // jump to label "Here"
}
}
func show_for_loop() {
fmt.Println("\n#show_for_loop()")
sum := 0
for index := 0; index < 10; index++ {
sum += index
}
fmt.Println("part 1, sum is equal to ", sum)
sum = 1
// The compiler will remove the `;` from the line below.
// for ; sum < 1000 ; {
for sum < 1000 {
sum += sum
}
fmt.Println("part 2, sum is equal to ", sum)
for index := 10; 0 < index; index-- {
if index == 5 {
break // or continue
}
fmt.Println(index)
}
}
func show_loop_through_map() {
fmt.Println("\n#show_loop_through_map()")
m := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
fmt.Println("map value = ", m)
for k, v := range m {
fmt.Println("map's key: ", k)
fmt.Println("map's value: ", v)
}
}
func show_switch() {
fmt.Println("\n#show_switch()")
i := 10
switch i {
case 1:
fmt.Println("i is equal to 1")
case 2, 3, 4:
fmt.Println("i is equal to 2, 3 or 4")
case 10:
fmt.Println("i is equal to 10")
default:
fmt.Println("All I know is that i is an integer")
}
integer := 6
fmt.Println("integer =", integer)
switch integer {
case 4:
fmt.Println("integer == 4")
fallthrough
case 5:
fmt.Println("integer <= 5")
fallthrough
case 6:
fmt.Println("integer <= 6")
fallthrough
case 7:
fmt.Println("integer <= 7")
fallthrough
case 8:
fmt.Println("integer <= 8")
fallthrough
default:
fmt.Println("default case")
}
}
func show_defer() {
fmt.Println("\nshow_defer()")
defer fmt.Println("(last defer)")
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
}
func main() {
show_if()
show_if_var()
show_goto()
show_for_loop()
show_loop_through_map()
show_switch()
show_defer()
}

View File

@@ -0,0 +1,31 @@
// Example code for Chapter 2.3 from "Build Web Application with Golang"
// Purpose: Showing how to use `panic()` and `recover()`
package main
import (
"fmt"
"os"
)
var user = os.Getenv("USER")
func check_user() {
if user == "" {
panic("no value for $USER")
}
fmt.Println("Environment Variable `USER` =", user)
}
func throwsPanic(f func()) (b bool) {
defer func() {
if x := recover(); x != nil {
fmt.Println("Panic message =", x);
b = true
}
}()
f() // if f causes panic, it will recover
return
}
func main(){
didPanic := throwsPanic(check_user)
fmt.Println("didPanic =", didPanic)
}

View File

@@ -0,0 +1,31 @@
// Example code for Chapter 2.3 from "Build Web Application with Golang"
// Purpose: Shows passing a variable by value and reference
package main
import "fmt"
func add_by_value(a int) int {
a = a + 1
return a
}
func add_by_reference(a *int) int {
*a = *a + 1
return *a
}
func show_add_by_value() {
x := 3
fmt.Println("x = ", x)
fmt.Println("add_by_value(x) =", add_by_value(x) )
fmt.Println("x = ", x)
}
func show_add_by_reference() {
x := 3
fmt.Println("x = ", x)
// &x pass memory address of x
fmt.Println("add_by_reference(&x) =", add_by_reference(&x) )
fmt.Println("x = ", x)
}
func main() {
show_add_by_value()
show_add_by_reference()
}

View File

@@ -0,0 +1,44 @@
// Example code for Chapter 2.3 from "Build Web Application with Golang"
// Purpose: Shows how to define a function type
package main
import "fmt"
type testInt func(int) bool // define a function type of variable
func isOdd(integer int) bool {
if integer%2 == 0 {
return false
}
return true
}
func isEven(integer int) bool {
if integer%2 == 0 {
return true
}
return false
}
// pass the function `f` as an argument to another function
func filter(slice []int, f testInt) []int {
var result []int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
func init() {
fmt.Println("\n#init() was called.")
}
func main() {
slice := []int{1, 2, 3, 4, 5, 7}
fmt.Println("slice = ", slice)
odd := filter(slice, isOdd) // use function as values
fmt.Println("Odd elements of slice are: ", odd)
even := filter(slice, isEven)
fmt.Println("Even elements of slice are: ", even)
}

View File

@@ -0,0 +1,20 @@
// Example code for Chapter 2.3 from "Build Web Application with Golang"
// Purpose: Shows how to return multiple values from a function
package main
import "fmt"
// return results of A + B and A * B
func SumAndProduct(A, B int) (int, int) {
return A + B, A * B
}
func main() {
x := 3
y := 4
xPLUSy, xTIMESy := SumAndProduct(x, y)
fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
}

View File

@@ -0,0 +1,43 @@
// Example code for Chapter 2.4 from "Build Web Application with Golang"
// Purpose: Shows you how to pass and use structs.
package main
import "fmt"
// define a new type
type person struct {
name string
age int
}
// compare age of two people, return the older person and differences of age
// struct is passed by value
func Older(p1, p2 person) (person, int) {
if p1.age > p2.age {
return p1, p1.age - p2.age
}
return p2, p2.age - p1.age
}
func main() {
var tom person
// initialization
tom.name, tom.age = "Tom", 18
// initialize two values by format "field:value"
bob := person{age: 25, name: "Bob"}
// initialize two values with order
paul := person{"Paul", 43}
tb_Older, tb_diff := Older(tom, bob)
tp_Older, tp_diff := Older(tom, paul)
bp_Older, bp_diff := Older(bob, paul)
fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, bob.name, tb_Older.name, tb_diff)
fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, paul.name, tp_Older.name, tp_diff)
fmt.Printf("Of %s and %s, %s is older by %d years\n", bob.name, paul.name, bp_Older.name, bp_diff)
}

View File

@@ -0,0 +1,39 @@
// Example code for Chapter 2.4 from "Build Web Application with Golang"
// Purpose: Example of embedded fields
package main
import "fmt"
type Human struct {
name string
age int
weight int
}
type Student struct {
Human // anonymous field, it means Student struct includes all fields that Human has.
speciality string
}
func main() {
// initialize a student
mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
// access fields
fmt.Println("His name is ", mark.name)
fmt.Println("His age is ", mark.age)
fmt.Println("His weight is ", mark.weight)
fmt.Println("His speciality is ", mark.speciality)
// modify notes
mark.speciality = "AI"
fmt.Println("Mark changed his speciality")
fmt.Println("His speciality is ", mark.speciality)
// modify age
fmt.Println("Mark become old")
mark.age = 46
fmt.Println("His age is", mark.age)
// modify weight
fmt.Println("Mark is not an athlete any more")
mark.weight += 60
fmt.Println("His weight is", mark.weight)
}

View File

@@ -0,0 +1,39 @@
// Example code for Chapter 2.4 from "Build Web Application with Golang"
// Purpose: Another example of embedded fields
package main
import "fmt"
type Skills []string
type Human struct {
name string
age int
weight int
}
type Student struct {
Human // struct as embedded field
Skills // string slice as embedded field
int // built-in type as embedded field
speciality string
}
func main() {
// initialize Student Jane
jane := Student{Human: Human{"Jane", 35, 100}, speciality: "Biology"}
// access fields
fmt.Println("Her name is ", jane.name)
fmt.Println("Her age is ", jane.age)
fmt.Println("Her weight is ", jane.weight)
fmt.Println("Her speciality is ", jane.speciality)
// modify value of skill field
jane.Skills = []string{"anatomy"}
fmt.Println("Her skills are ", jane.Skills)
fmt.Println("She acquired two new ones ")
jane.Skills = append(jane.Skills, "physics", "golang")
fmt.Println("Her skills now are ", jane.Skills)
// modify embedded field
jane.int = 3
fmt.Println("Her preferred number is", jane.int)
}

View File

@@ -0,0 +1,24 @@
// Example code for Chapter 2.4 from "Build Web Application with Golang"
// Purpose: Shows a name conflict with a embedded field
package main
import "fmt"
type Human struct {
name string
age int
phone string // Human has phone field
}
type Employee struct {
Human // embedded field Human
speciality string
phone string // phone in employee
}
func main() {
Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
fmt.Println("Bob's work phone is:", Bob.phone)
// access phone field in Human
fmt.Println("Bob's personal phone is:", Bob.Human.phone)
}

View File

@@ -0,0 +1,39 @@
// Example code for Chapter 2.4 from "Build Web Application with Golang"
// Purpose: Shows different ways of creating a struct
package main
import "fmt"
func show_basic_struct() {
fmt.Println("\nshow_basic_struct()")
type person struct {
name string
age int
}
var P person // p is person type
P.name = "Astaxie" // assign "Astaxie" to the filed 'name' of p
P.age = 25 // assign 25 to field 'age' of p
fmt.Printf("The person's name is %s\n", P.name) // access field 'name' of p
tom := person{"Tom", 25}
bob := person{age: 24, name: "Bob"}
fmt.Printf("tom = %+v\n", tom)
fmt.Printf("bob = %#v\n", bob)
}
func show_anonymous_struct() {
fmt.Println("\nshow_anonymous_struct()")
fmt.Printf("Anonymous struct = %#v\n", struct {
name string
count int
}{
"counter", 1,
})
}
func main() {
show_basic_struct()
show_anonymous_struct()
}

View File

@@ -0,0 +1,36 @@
// Example code from Chapter 2.5
// Attach method to struct.
package main
import (
"fmt"
"math"
)
type Rectangle struct {
width, height float64
}
type Circle struct {
radius float64
}
func (r Rectangle) area() float64 {
return r.width * r.height
}
func (c Circle) area() float64 {
return c.radius * c.radius * math.Pi
}
func main() {
r1 := Rectangle{12, 2}
r2 := Rectangle{9, 4}
c1 := Circle{10}
c2 := Circle{25}
fmt.Println("Area of r1 is: ", r1.area())
fmt.Println("Area of r2 is: ", r2.area())
fmt.Println("Area of c1 is: ", c1.area())
fmt.Println("Area of c2 is: ", c2.area())
}

View File

@@ -0,0 +1,73 @@
package main
import "fmt"
const (
WHITE = iota
BLACK
BLUE
RED
YELLOW
)
type Color byte
type Box struct {
width, height, depth float64
color Color
}
type BoxList []Box //a slice of boxes
func (b Box) Volume() float64 {
return b.width * b.height * b.depth
}
func (b *Box) SetColor(c Color) {
b.color = c
}
func (bl BoxList) BiggestsColor() Color {
v := 0.00
k := Color(WHITE)
for _, b := range bl {
if b.Volume() > v {
v = b.Volume()
k = b.color
}
}
return k
}
func (bl BoxList) PaintItBlack() {
for i, _ := range bl {
bl[i].SetColor(BLACK)
}
}
func (c Color) String() string {
strings := []string{"WHITE", "BLACK", "BLUE", "RED", "YELLOW"}
return strings[c]
}
func main() {
boxes := BoxList{
Box{4, 4, 4, RED},
Box{10, 10, 1, YELLOW},
Box{1, 1, 20, BLACK},
Box{10, 10, 1, BLUE},
Box{10, 30, 1, WHITE},
Box{20, 20, 20, YELLOW},
}
fmt.Printf("We have %d boxes in our set\n", len(boxes))
fmt.Println("The volume of the first one is", boxes[0].Volume(), "cm³")
fmt.Println("The color of the last one is", boxes[len(boxes)-1].color.String())
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
fmt.Println("Let's paint them all black")
boxes.PaintItBlack()
fmt.Println("The color of the second one is", boxes[1].color.String())
fmt.Println("Obviously, now, the biggest one is", boxes.BiggestsColor().String())
}

View File

@@ -0,0 +1,31 @@
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human // anonymous field
school string
}
type Employee struct {
Human
company string
}
// define a method in Human
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func main() {
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
mark.SayHi()
sam.SayHi()
}

View File

@@ -0,0 +1,36 @@
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human
school string
}
type Employee struct {
Human
company string
}
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
func main() {
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
mark.SayHi()
sam.SayHi()
}

View File

@@ -0,0 +1,18 @@
package main
import "fmt"
type Rectangle struct {
width, height float64
}
func area(r Rectangle) float64 {
return r.width * r.height
}
func main() {
r1 := Rectangle{12, 2}
r2 := Rectangle{9, 4}
fmt.Println("Area of r1 is: ", area(r1))
fmt.Println("Area of r2 is: ", area(r2))
}

View File

@@ -0,0 +1,71 @@
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human
school string
loan float32
}
type Employee struct {
Human
company string
money float32
}
func (h Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func (h Human) Sing(lyrics string) {
fmt.Println("La la la la...", lyrics)
}
func (e Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
// Interface Men implemented by Human, Student and Employee
type Men interface {
SayHi()
Sing(lyrics string)
}
func main() {
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
Tom := Employee{Human{"Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000}
// define interface i
var i Men
//i can store Student
i = mike
fmt.Println("This is Mike, a Student:")
i.SayHi()
i.Sing("November rain")
//i can store Employee
i = Tom
fmt.Println("This is Tom, an Employee:")
i.SayHi()
i.Sing("Born to be wild")
// slice of Men
fmt.Println("Let's use a slice of Men and see what happens")
x := make([]Men, 3)
// these three elements are different types but they all implemented interface Men
x[0], x[1], x[2] = paul, sam, mike
for _, value := range x{
value.SayHi()
}
}

View File

@@ -0,0 +1,33 @@
package main
import (
"fmt"
"reflect"
)
func show_interface_none() {
fmt.Println("\nshow_interface_none()")
var a interface{}
a = "string"
a = 1
a = false
fmt.Println("a =", a)
}
func show_reflection() {
fmt.Println("\nshow_reflection()")
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
fmt.Println("value:", v.Float())
p := reflect.ValueOf(&x)
newX := p.Elem()
newX.SetFloat(7.1)
fmt.Println("newX =", newX)
fmt.Println("newX float64() value:", newX.Float())
}
func main() {
show_interface_none()
show_reflection()
}

View File

@@ -0,0 +1,22 @@
package main
import (
"fmt"
"strconv"
)
type Human struct {
name string
age int
phone string
}
// Human implemented fmt.Stringer
func (h Human) String() string {
return "Name:" + h.name + ", Age:" + strconv.Itoa(h.age) + " years, Contact:" + h.phone
}
func main() {
Bob := Human{"Bob", 39, "000-7777-XXX"}
fmt.Println("This Human is : ", Bob)
}

View File

@@ -0,0 +1,38 @@
package main
import (
"fmt"
"strconv"
)
type Element interface{}
type List []Element
type Person struct {
name string
age int
}
func (p Person) String() string {
return "(name: " + p.name + " - age: " + strconv.Itoa(p.age) + " years)"
}
func main() {
list := make(List, 3)
list[0] = 1 //an int
list[1] = "Hello" //a string
list[2] = Person{"Dennis", 70}
for index, element := range list {
switch value := element.(type) {
case int:
fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
case string:
fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
case Person:
fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
default:
fmt.Println("list[%d] is of a different type", index)
}
}
}

View File

@@ -0,0 +1,37 @@
package main
import (
"fmt"
"strconv"
)
type Element interface{}
type List []Element
type Person struct {
name string
age int
}
func (p Person) String() string {
return "(name: " + p.name + " - age: " + strconv.Itoa(p.age) + " years)"
}
func main() {
list := make(List, 3)
list[0] = 1 // an int
list[1] = "Hello" // a string
list[2] = Person{"Dennis", 70}
for index, element := range list {
if value, ok := element.(int); ok {
fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
} else if value, ok := element.(string); ok {
fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
} else if value, ok := element.(Person); ok {
fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
} else {
fmt.Println("list[%d] is of a different type", index)
}
}
}

View File

@@ -0,0 +1,13 @@
// Example code for Chapter 2.7 from "Build Web Application with Golang"
// Purpose: Shows how to use a buffered channel
package main
import "fmt"
func main() {
c := make(chan int, 2) // change 2 to 1 will have runtime error, but 3 is fine
c <- 1
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}

View File

@@ -0,0 +1,20 @@
// Example code for Chapter 2.7 from "Build Web Application with Golang"
// Purpose: Shows how to launch a simple gorountine
package main
import (
"fmt"
"runtime"
)
func say(s string) {
for i := 0; i < 5; i++ {
runtime.Gosched()
fmt.Println(s)
}
}
func main() {
go say("world") // create a new goroutine
say("hello") // current goroutine
}

View File

@@ -0,0 +1,24 @@
// Example code for Chapter 2.7 from "Build Web Application with Golang"
// Purpose: Shows how to close and interate through a channel
package main
import (
"fmt"
)
func fibonacci(n int, c chan int) {
x, y := 1, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}

View File

@@ -0,0 +1,30 @@
// Example code for Chapter 2.7 from "Build Web Application with Golang"
// Purpose: Shows how to use `select`
package main
import "fmt"
func fibonacci(c, quit chan int) {
x, y := 1, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
func main() {
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
fibonacci(c, quit)
}

View File

@@ -0,0 +1,27 @@
// Example code for Chapter 2.7 from "Build Web Application with Golang"
// Purpose: Shows how to create and use a timeout
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
o := make(chan bool)
go func() {
for {
select {
case v := <-c:
fmt.Println(v)
case <-time.After(5 * time.Second):
fmt.Println("timeout")
o <- true
break
}
}
}()
<-o
}

View File

@@ -0,0 +1,24 @@
// Example code for Chapter 2.7 from "Build Web Application with Golang"
// Purpose: Shows how to create and use a unbuffered channel
package main
import "fmt"
func sum(a []int, c chan int) {
total := 0
for _, v := range a {
total += v
}
c <- total // send total to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}

View File

@@ -0,0 +1,31 @@
// Example code for Chapter 3.2 from "Build Web Application with Golang"
// Purpose: Shows how to acces the form values from the request
package main
import (
"fmt"
"log"
"net/http"
"strings"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() // parse arguments, you have to call this by yourself
fmt.Println(r.Form) // print form information in server side
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello astaxie!") // send data to client side
}
func main() {
http.HandleFunc("/", sayhelloName) // set router
err := http.ListenAndServe(":9090", nil) // set listen port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}

View File

@@ -0,0 +1,30 @@
// Example code for Chapter 3.4 from "Build Web Application with Golang"
// Purpose: Shows how to create a handler for `http.ListenAndServe()`
// Run `go run main.go` then access `http://localhost:9090`
package main
import (
"fmt"
"net/http"
)
type MyMux struct {
}
func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
sayhelloName(w, r)
return
}
http.NotFound(w, r)
return
}
func sayhelloName(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello myroute!")
}
func main() {
mux := &MyMux{}
http.ListenAndServe(":9090", mux)
}

View File

@@ -0,0 +1,12 @@
<html>
<head>
<title></title>
</head>
<body>
<form action="/login" method="post">
Username:<input type="text" name="username">
Password:<input type="password" name="password">
<input type="submit" value="Login">
</form>
</body>
</html>

View File

@@ -0,0 +1,48 @@
// Example code for Chapter 4.1 from "Build Web Application with Golang"
// Purpose: Shows how to create a simple login using a template
// Run: `go run main.go`, then access `http://localhost:9090` and `http://localhost:9090/login`
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"strings"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //Parse url parameters passed, then parse the response packet for the POST body (request body)
// attention: If you do not call ParseForm method, the following data can not be obtained form
fmt.Println(r.Form) // print information on server side.
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello astaxie!") // write data to response
}
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //get request method
if r.Method == "GET" {
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, nil)
} else {
r.ParseForm()
// logic part of log in
fmt.Println("username:", r.Form["username"])
fmt.Println("password:", r.Form["password"])
}
}
func main() {
http.HandleFunc("/", sayhelloName) // setting router rule
http.HandleFunc("/login", login)
err := http.ListenAndServe(":9090", nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}

View File

@@ -0,0 +1,59 @@
// Example code for Chapter 4.2 from "Build Web Application with Golang"
// Purpose: Shows how to perform server-side validation of user input from a form.
// Also shows to use multiple template files with predefined template names.
// Run `go run main.go` and then access http://localhost:9090
package main
import (
"apps/ch.4.2/validator"
"html/template"
"log"
"net/http"
)
const (
PORT = "9090"
HOST_URL = "http://localhost:" + PORT
)
var t *template.Template
type Links struct {
BadLinks [][2]string
}
// invalid links to display for testing.
var links Links
func index(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, HOST_URL+"/profile", http.StatusTemporaryRedirect)
}
func profileHandler(w http.ResponseWriter, r *http.Request) {
t.ExecuteTemplate(w, "profile", links)
}
func checkProfile(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
p := validator.ProfilePage{&r.Form}
t.ExecuteTemplate(w, "submission", p.GetErrors())
}
// This function is called before main()
func init() {
// Note: we can reference the loaded templates by their defined name inside the template files.
t = template.Must(template.ParseFiles("profile.gtpl", "submission.gtpl"))
list := make([][2]string, 2)
list[0] = [2]string{HOST_URL + "/checkprofile", "No data"}
list[1] = [2]string{HOST_URL + "/checkprofile?age=1&gender=guy&shirtsize=big", "Invalid options"}
links = Links{list}
}
func main() {
http.HandleFunc("/", index)
http.HandleFunc("/profile", profileHandler)
http.HandleFunc("/checkprofile", checkProfile)
err := http.ListenAndServe(":"+PORT, nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}

View File

@@ -0,0 +1,89 @@
{{define "profile"}}<!DOCTYPE html>
<html>
<style>
.row{
display: table-row;
}
.cell{
display: table-cell;
}
.required{
color: red
}
</style>
<body>
<h2>Profile Setup:</h2>
<form action="/checkprofile">
<div class="row">
<div class="cell"><span class="required">*</span>User Name:</div>
<div class="cell"><input type="text" name="username" id="username" required/></div>
</div>
<div class="row">
<div class="cell"><span class="required">*</span>Age:</div>
<div class="cell"><input type="number" min="13" max="130" name="age" id="age" size="3" required/></div>
</div>
<div class="row">
<div class="cell"><span class="required">*</span>Email:</div>
<div class="cell"><input type="email" name="email" id="email" placeholder="john@example.com" required/></div>
</div>
<div class="row">
<div class="cell"><span class="required">*</span>Birth day:</div>
<div class="cell">
<input type="date" name="birthday" id="birthday" placeholder="MM/DD/YYYY" required/>
</div>
</div>
<div class="row">
<div class="cell">Gender:</div>
<div class="cell">
<label for="gender_male">
Male: <input type="radio" name="gender" value="m" id="gender_male"/>
</label>
<label for="gender_female">
Female: <input type="radio" name="gender" value="f" id="gender_female"/>
</label>
<label for="gender_na">
N/A: <input type="radio" name="gender" value="na" id="gender_na"/>
</label>
</div>
</div>
<div class="row">
<div class="cell">Siblings:</div>
<div class="cell">
<label for="sibling_male">
Brother: <input type="checkbox" name="sibling" value="m" id="sibling_male"/>
</label>
<label for="sibling_female">
Sister: <input type="checkbox" name="sibling" value="f" id="sibling_female"/>
</label>
</div>
</div>
<div class="row">
<div class="cell">Shirt Size:</div>
<div class="cell">
<select id="shirt_size" >
<option></option>
<option value="s">Small</option>
<option value="m">Medium</option>
<option value="l">Large</option>
<option value="xl">X-Large</option>
<option value="xxl">XX-Large</option>
</select>
</div>
</div>
<div class="row">
<div class="cell">Chinese Name:</div>
<div class="cell"><input type="text" name="chineseName" id="chineseName"/></div>
</div>
<br/>
<span class="required">*</span>Required
<br/>
<input type="submit" value="Submit" id="submitBtn"/>
</form>
<h2>Invalid submissions</h2>
<ol>{{range .BadLinks}}
<li><a href="{{index . 0}}">{{index . 1}}</a></li>
{{end}}
</ol>
</body>
</html>
{{end}}

View File

@@ -0,0 +1,16 @@
{{define "submission"}}<!DOCTYPE html>
<html>
<body>
{{if .Errors}}
<h2>Errors:</h2>
<ol>
{{range .Errors}}
<li>{{.}}</li>
{{end}}
</ol>
{{else}}
Profile successfully submitted.
{{end}}
</body>
</html>
{{end}}

View File

@@ -0,0 +1,175 @@
// This file contains all the validators to validate the profile page.
package validator
import (
"errors"
"fmt"
"net/url"
"regexp"
"strconv"
"strings"
"time"
)
type ProfilePage struct {
Form *url.Values
}
type Errors struct {
Errors []error
}
// Goes through the form object and validates each element.
// Attachs an error to the output if validation fails.
func (p *ProfilePage) GetErrors() Errors {
errs := make([]error, 0, 10)
if *p.Form == nil || len(*p.Form) < 1 {
errs = append(errs, errors.New("No data was received. Please submit from the profile page."))
}
for name, val := range *p.Form {
if fn, ok := stringValidator[name]; ok {
if err := fn(strings.Join(val, "")); err != nil {
errs = append(errs, err)
}
} else {
if fn, ok := stringsValidator[name]; ok {
if err := fn(val); err != nil {
errs = append(errs, err)
}
}
}
}
return Errors{errs}
}
const (
// Used for parsing the time
mmddyyyyForm = "01/02/2006" // we want the date sent in this format
yyyymmddForm = "2006-01-02" // However, HTML5 pages send the date in this format
)
var stringValidator map[string]func(string) error = map[string]func(string) error{
// parameter name : validator reference
"age": checkAge,
"birthday": checkDate,
"chineseName": checkChineseName,
"email": checkEmail,
"gender": checkGender,
"shirtsize": checkShirtSize,
"username": checkUsername,
}
var stringsValidator map[string]func([]string) error = map[string]func([]string) error{
// parameter name : validator reference
"sibling": checkSibling,
}
// Returns true if slices have a common element
func doSlicesIntersect(s1, s2 []string) bool {
if s1 == nil || s2 == nil {
return false
}
for _, str := range s1 {
if isElementInSlice(str, s2) {
return true
}
}
return false
}
func isElementInSlice(str string, sl []string) bool {
if sl == nil || str == "" {
return false
}
for _, v := range sl {
if v == str {
return true
}
}
return false
}
// Checks if all the characters are chinese characters. Won't check if empty.'
func checkChineseName(str string) error {
if str != "" {
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", strings.Trim(str, " ")); !m {
return errors.New("Please make sure that the chinese name only contains chinese characters.")
}
}
return nil
}
// Checks if a user name exist.
func checkUsername(str string) error {
if strings.Trim(str, " ") == "" {
return errors.New("Please enter a username.")
}
return nil
}
// Check if age is a number and between 13 and 130
func checkAge(str string) error {
age, err := strconv.Atoi(str)
if str == "" || err != nil {
return errors.New("Please enter a valid age.")
}
if age < 13 {
return errors.New("You must be at least 13 years of age to submit.")
}
if age > 130 {
return errors.New("You're too old to register, grandpa.")
}
return nil
}
func checkEmail(str string) error {
if m, err := regexp.MatchString(`^[^@]+@[^@]+$`, str); !m {
fmt.Println("err = ", err)
return errors.New("Please enter a valid email address.")
}
return nil
}
// Checks if a valid date was passed.
func checkDate(str string) error {
_, err := time.Parse(mmddyyyyForm, str)
if err != nil {
_, err = time.Parse(yyyymmddForm, str)
}
if str == "" || err != nil {
return errors.New("Please enter a valid Date.")
}
return nil
}
// Checks if the passed input is a known gender option
func checkGender(str string) error {
if str == "" {
return nil
}
siblings := []string{"m", "f", "na"}
if !isElementInSlice(str, siblings) {
return errors.New("Please select a valid gender.")
}
return nil
}
// Check if all the values are known options.
func checkSibling(strs []string) error {
if strs == nil || len(strs) < 1 {
return nil
}
siblings := []string{"m", "f"}
if siblings != nil && !doSlicesIntersect(siblings, strs) {
return errors.New("Please select a valid sibling")
}
return nil
}
// Checks if the shirt size is a known option.
func checkShirtSize(str string) error {
if str == "" {
return nil
}
shirts := []string{"s", "m", "l", "xl", "xxl"}
if !isElementInSlice(str, shirts) {
return errors.New("Please select a valid shirt size")
}
return nil
}

View File

@@ -0,0 +1,28 @@
<!doctype html>
<html>
<body>
<h2>Cross Site Scripting Attack Test</h2>
{{if .}}
Previous User Input: <br/>
<code><pre>{{.}}</pre></code>
{{end}}
<form action="/">
<label>
User Input:
<input type="text" size=50 name="userinput" id="userinput"/>
</label>
<br/>
<label>
Escape Input:
<input type="checkbox" value="1" name="escape" id="escape"/>
</label>
<br/>
<input type="submit" id="submitBtn" value="Submit"/>
</form>
<script type="text/javascript">
var s = "<scri"+"pt>alert('pOwned by XSS.')</scri"+"pt>"
document.getElementById("userinput").value = s;
</script>
</body>
</html>

View File

@@ -0,0 +1,39 @@
// Example code for Chapter 4.3 from "Build Web Application with Golang"
// Purpose: Shows how to properly escape input
package main
import (
"html/template"
"net/http"
textTemplate "text/template"
)
var t *template.Template = template.Must(template.ParseFiles("index.gtpl"))
func index(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
userInput := r.Form.Get("userinput")
if 0 < len(r.Form.Get("escape")) {
t.Execute(w, template.HTMLEscapeString(userInput))
} else {
// Variables with type `template.HTML` are not escaped when passed to `.Execute()`
t.Execute(w, template.HTML(userInput))
}
}
func templateHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
userInput := r.Form.Get("userinput")
if 0 < len(r.Form.Get("escape")) {
// `html/template.Execute()` escapes input
t.Execute(w, userInput)
} else {
tt := textTemplate.Must(textTemplate.ParseFiles("index.gtpl"))
// `text/template.Execute()` doesn't escape input
tt.Execute(w, userInput)
}
}
func main() {
http.HandleFunc("/", index)
http.HandleFunc("/template", templateHandler)
http.ListenAndServe(":9090", nil)
}

View File

@@ -0,0 +1,54 @@
// Example code for Chapter 3.2 from "Build Web Application with Golang"
// Purpose: Shows how to prevent duplicate submissions by using tokens
// Example code for Chapter 4.4 based off the code from Chapter 4.2
// Run `go run main.go` then access http://localhost:9090
package main
import (
"apps/ch.4.4/nonce"
"apps/ch.4.4/validator"
"html/template"
"log"
"net/http"
)
const (
PORT = "9090"
HOST_URL = "http://localhost:" + PORT
)
var submissions nonce.Nonces
var t *template.Template
func index(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, HOST_URL+"/profile", http.StatusTemporaryRedirect)
}
func profileHandler(w http.ResponseWriter, r *http.Request) {
t.ExecuteTemplate(w, "profile", submissions.NewNonce())
}
func checkProfile(w http.ResponseWriter, r *http.Request) {
var errs validator.Errors
r.ParseForm()
token := r.Form.Get("token")
if err := submissions.CheckThenMarkToken(token); err != nil {
errs = validator.Errors{[]error{err}}
} else {
p := validator.ProfilePage{&r.Form}
errs = p.GetErrors()
}
t.ExecuteTemplate(w, "submission", errs)
}
func init() {
submissions = nonce.New()
t = template.Must(template.ParseFiles("profile.gtpl", "submission.gtpl"))
}
func main() {
http.HandleFunc("/", index)
http.HandleFunc("/profile", profileHandler)
http.HandleFunc("/checkprofile", checkProfile)
err := http.ListenAndServe(":"+PORT, nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}

View File

@@ -0,0 +1,70 @@
// A nonce is a number or string used only once.
// This is useful for generating a unique token for login pages to prevent duplicate submissions.
package nonce
import (
"crypto/md5"
"errors"
"fmt"
"io"
"math/rand"
"strconv"
"time"
)
// Contains a unique token
type Nonce struct {
Token string
}
// Keeps track of marked/used tokens
type Nonces struct {
hashs map[string]bool
}
func New() Nonces {
return Nonces{make(map[string]bool)}
}
func (n *Nonces) NewNonce() Nonce {
return Nonce{n.NewToken()}
}
// Returns a new unique token
func (n *Nonces) NewToken() string {
t := createToken()
for n.HasToken(t) {
t = createToken()
}
return t
}
// Checks if token has been marked.
func (n *Nonces) HasToken(token string) bool {
return n.hashs[token] == true
}
func (n *Nonces) MarkToken(token string) {
n.hashs[token] = true
}
func (n *Nonces) CheckToken(token string) error {
if token == "" {
return errors.New("No token supplied")
}
if n.HasToken(token) {
return errors.New("Duplicate submission.")
}
return nil
}
func (n *Nonces) CheckThenMarkToken(token string) error {
defer n.MarkToken(token)
if err := n.CheckToken(token); err != nil {
return err
}
return nil
}
func createToken() string {
h := md5.New()
now := time.Now().Unix()
io.WriteString(h, strconv.FormatInt(now, 10))
io.WriteString(h, strconv.FormatInt(rand.Int63(), 10))
return fmt.Sprintf("%x", h.Sum(nil))
}

View File

@@ -0,0 +1,85 @@
{{define "profile"}}<!DOCTYPE html>
<html>
<style>
.row{
display: table-row;
}
.cell{
display: table-cell;
}
.required{
color: red
}
</style>
<body>
<h2>Profile Setup:</h2>
<form action="/checkprofile" method="POST">
<div class="row">
<div class="cell"><span class="required">*</span>User Name:</div>
<div class="cell"><input type="text" name="username" id="username" required/></div>
</div>
<div class="row">
<div class="cell"><span class="required">*</span>Age:</div>
<div class="cell"><input type="number" min="13" max="130" name="age" id="age" size="3" required/></div>
</div>
<div class="row">
<div class="cell"><span class="required">*</span>Email:</div>
<div class="cell"><input type="email" name="email" id="email" placeholder="john@example.com" required/></div>
</div>
<div class="row">
<div class="cell"><span class="required">*</span>Birth day:</div>
<div class="cell">
<input type="date" name="birthday" id="birthday" placeholder="MM/DD/YYYY" required/>
</div>
</div>
<div class="row">
<div class="cell">Gender:</div>
<div class="cell">
<label for="gender_male">
Male: <input type="radio" name="gender" value="m" id="gender_male"/>
</label>
<label for="gender_female">
Female: <input type="radio" name="gender" value="f" id="gender_female"/>
</label>
<label for="gender_na">
N/A: <input type="radio" name="gender" value="na" id="gender_na"/>
</label>
</div>
</div>
<div class="row">
<div class="cell">Siblings:</div>
<div class="cell">
<label for="sibling_male">
Brother: <input type="checkbox" name="sibling" value="m" id="sibling_male"/>
</label>
<label for="sibling_female">
Sister: <input type="checkbox" name="sibling" value="f" id="sibling_female"/>
</label>
</div>
</div>
<div class="row">
<div class="cell">Shirt Size:</div>
<div class="cell">
<select id="shirt_size" >
<option></option>
<option value="s">Small</option>
<option value="m">Medium</option>
<option value="l">Large</option>
<option value="xl">X-Large</option>
<option value="xxl">XX-Large</option>
</select>
</div>
</div>
<div class="row">
<div class="cell">Chinese Name:</div>
<div class="cell"><input type="text" name="chineseName" id="chineseName"/></div>
</div>
<br/>
<span class="required">*</span>Required
<br/>
<input type="hidden" name="token" value="{{.Token}}"/>
<input type="submit" value="Submit" id="submitBtn"/>
</form>
</body>
</html>
{{end}}

View File

@@ -0,0 +1,17 @@
{{define "submission"}}<!DOCTYPE html>
<html>
<body>
{{if .Errors}}
<h2>Errors:</h2>
<ol>
{{range .Errors}}
<li>{{.}}</li>
{{end}}
</ol>
{{else}}
Profile successfully submitted.<br/>
Note: Refreshing the page will produce a duplicate entry.
{{end}}
</body>
</html>
{{end}}

View File

@@ -0,0 +1,175 @@
// This file contains all the validators to validate the profile page.
package validator
import (
"errors"
"fmt"
"net/url"
"regexp"
"strconv"
"strings"
"time"
)
type ProfilePage struct {
Form *url.Values
}
type Errors struct {
Errors []error
}
// Goes through the form object and validates each element.
// Attachs an error to the output if validation fails.
func (p *ProfilePage) GetErrors() Errors {
errs := make([]error, 0, 10)
if *p.Form == nil || len(*p.Form) < 1 {
errs = append(errs, errors.New("No data was received. Please submit from the profile page."))
}
for name, val := range *p.Form {
if fn, ok := stringValidator[name]; ok {
if err := fn(strings.Join(val, "")); err != nil {
errs = append(errs, err)
}
} else {
if fn, ok := stringsValidator[name]; ok {
if err := fn(val); err != nil {
errs = append(errs, err)
}
}
}
}
return Errors{errs}
}
const (
// Used for parsing the time
mmddyyyyForm = "01/02/2006" // we want the date sent in this format
yyyymmddForm = "2006-01-02" // However, HTML5 pages send the date in this format
)
var stringValidator map[string]func(string) error = map[string]func(string) error{
// parameter name : validator reference
"age": checkAge,
"birthday": checkDate,
"chineseName": checkChineseName,
"email": checkEmail,
"gender": checkGender,
"shirtsize": checkShirtSize,
"username": checkUsername,
}
var stringsValidator map[string]func([]string) error = map[string]func([]string) error{
// parameter name : validator reference
"sibling": checkSibling,
}
// Returns true if slices have a common element
func doSlicesIntersect(s1, s2 []string) bool {
if s1 == nil || s2 == nil {
return false
}
for _, str := range s1 {
if isElementInSlice(str, s2) {
return true
}
}
return false
}
func isElementInSlice(str string, sl []string) bool {
if sl == nil || str == "" {
return false
}
for _, v := range sl {
if v == str {
return true
}
}
return false
}
// Checks if all the characters are chinese characters. Won't check if empty.'
func checkChineseName(str string) error {
if str != "" {
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", strings.Trim(str, " ")); !m {
return errors.New("Please make sure that the chinese name only contains chinese characters.")
}
}
return nil
}
// Checks if a user name exist.
func checkUsername(str string) error {
if strings.Trim(str, " ") == "" {
return errors.New("Please enter a username.")
}
return nil
}
// Check if age is a number and between 13 and 130
func checkAge(str string) error {
age, err := strconv.Atoi(str)
if str == "" || err != nil {
return errors.New("Please enter a valid age.")
}
if age < 13 {
return errors.New("You must be at least 13 years of age to submit.")
}
if age > 130 {
return errors.New("You're too old to register, grandpa.")
}
return nil
}
func checkEmail(str string) error {
if m, err := regexp.MatchString(`^[^@]+@[^@]+$`, str); !m {
fmt.Println("err = ", err)
return errors.New("Please enter a valid email address.")
}
return nil
}
// Checks if a valid date was passed.
func checkDate(str string) error {
_, err := time.Parse(mmddyyyyForm, str)
if err != nil {
_, err = time.Parse(yyyymmddForm, str)
}
if str == "" || err != nil {
return errors.New("Please enter a valid Date.")
}
return nil
}
// Checks if the passed input is a known gender option
func checkGender(str string) error {
if str == "" {
return nil
}
siblings := []string{"m", "f", "na"}
if !isElementInSlice(str, siblings) {
return errors.New("Please select a valid gender.")
}
return nil
}
// Check if all the values are known options.
func checkSibling(strs []string) error {
if strs == nil || len(strs) < 1 {
return nil
}
siblings := []string{"m", "f"}
if siblings != nil && !doSlicesIntersect(siblings, strs) {
return errors.New("Please select a valid sibling")
}
return nil
}
// Checks if the shirt size is a known option.
func checkShirtSize(str string) error {
if str == "" {
return nil
}
shirts := []string{"s", "m", "l", "xl", "xxl"}
if !isElementInSlice(str, shirts) {
return errors.New("Please select a valid shirt size")
}
return nil
}

View File

@@ -0,0 +1,46 @@
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
)
func checkError(err error) {
if err != nil {
panic(err)
}
}
func postFile(filename string, targetUrl string) {
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
fileWriter, err := bodyWriter.CreateFormFile("uploadfile", filename)
checkError(err)
fh, err := os.Open(filename)
checkError(err)
_, err = io.Copy(fileWriter, fh)
checkError(err)
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
resp, err := http.Post(targetUrl, contentType, bodyBuf)
checkError(err)
defer resp.Body.Close()
resp_body, err := ioutil.ReadAll(resp.Body)
checkError(err)
fmt.Println(resp.Status)
fmt.Println(string(resp_body))
}
func main() {
target_url := "http://localhost:9090/upload"
filename := "../file.txt"
postFile(filename, target_url)
}

View File

@@ -0,0 +1,15 @@
{{define "index"}}
<!doctype html>
<html>
<head>
<title>Upload file</title>
</head>
<body>
<form enctype="multipart/form-data" action="http://127.0.0.1:9090/upload" method="post">
<input type="file" name="uploadfile" />
<input type="hidden" name="token" value="{{.}}"/>
<input type="submit" value="upload" />
</form>
</body>
</html>
{{end}}

View File

@@ -0,0 +1,64 @@
// Example code for Chapter 4.5
// Purpose is to create a server to handle uploading files.
package main
import (
"apps/ch.4.4/nonce"
"apps/ch.4.4/validator"
"fmt"
"html/template"
"io"
"mime/multipart"
"net/http"
"os"
)
const MiB_UNIT = 1 << 20
var t *template.Template
var submissions nonce.Nonces = nonce.New()
func checkError(err error) {
if err != nil {
panic(err)
}
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
err := t.ExecuteTemplate(w, "index", submissions.NewToken())
checkError(err)
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
var errs validator.Errors
r.ParseMultipartForm(32 * MiB_UNIT)
token := r.Form.Get("token")
if err := submissions.CheckThenMarkToken(token); err != nil {
errs = validator.Errors{[]error{err}}
} else {
file, handler, err := r.FormFile("uploadfile")
checkError(err)
saveUpload(file, handler)
}
err := t.ExecuteTemplate(w, "upload", errs)
checkError(err)
}
func saveUpload(file multipart.File, handler *multipart.FileHeader) {
defer file.Close()
fmt.Printf("Uploaded file info: %#v", handler.Header)
localFilename := fmt.Sprintf("./uploads/%v.%v", handler.Filename, submissions.NewToken())
f, err := os.OpenFile(localFilename, os.O_WRONLY|os.O_CREATE, 0666)
checkError(err)
defer f.Close()
_, err = io.Copy(f, file)
checkError(err)
}
func init() {
var err error
t, err = template.ParseFiles("index.gtpl", "upload.gtpl")
checkError(err)
}
func main() {
http.HandleFunc("/", indexHandler)
http.HandleFunc("/upload", uploadHandler)
err := http.ListenAndServe(":9090", nil)
checkError(err)
}

View File

@@ -0,0 +1,70 @@
// A nonce is a number or string used only once.
// This is useful for generating a unique token for login pages to prevent duplicate submissions.
package nonce
import (
"crypto/md5"
"errors"
"fmt"
"io"
"math/rand"
"strconv"
"time"
)
// Contains a unique token
type Nonce struct {
Token string
}
// Keeps track of marked/used tokens
type Nonces struct {
hashs map[string]bool
}
func New() Nonces {
return Nonces{make(map[string]bool)}
}
func (n *Nonces) NewNonce() Nonce {
return Nonce{n.NewToken()}
}
// Returns a new unique token
func (n *Nonces) NewToken() string {
t := createToken()
for n.HasToken(t) {
t = createToken()
}
return t
}
// Checks if token has been marked.
func (n *Nonces) HasToken(token string) bool {
return n.hashs[token] == true
}
func (n *Nonces) MarkToken(token string) {
n.hashs[token] = true
}
func (n *Nonces) CheckToken(token string) error {
if token == "" {
return errors.New("No token supplied")
}
if n.HasToken(token) {
return errors.New("Duplicate submission.")
}
return nil
}
func (n *Nonces) CheckThenMarkToken(token string) error {
defer n.MarkToken(token)
if err := n.CheckToken(token); err != nil {
return err
}
return nil
}
func createToken() string {
h := md5.New()
now := time.Now().Unix()
io.WriteString(h, strconv.FormatInt(now, 10))
io.WriteString(h, strconv.FormatInt(rand.Int63(), 10))
return fmt.Sprintf("%x", h.Sum(nil))
}

View File

@@ -0,0 +1,17 @@
{{define "upload"}}<!DOCTYPE html>
<html>
<body>
{{if .Errors}}
<h2>Errors:</h2>
<ol>
{{range .Errors}}
<li>{{.}}</li>
{{end}}
</ol>
{{else}}
File uploaded successfully.<br/>
Note: Refreshing the page will produce a duplicate entry.
{{end}}
</body>
</html>
{{end}}

View File

@@ -0,0 +1,175 @@
// This file contains all the validators to validate the profile page.
package validator
import (
"errors"
"fmt"
"net/url"
"regexp"
"strconv"
"strings"
"time"
)
type ProfilePage struct {
Form *url.Values
}
type Errors struct {
Errors []error
}
// Goes through the form object and validates each element.
// Attachs an error to the output if validation fails.
func (p *ProfilePage) GetErrors() Errors {
errs := make([]error, 0, 10)
if *p.Form == nil || len(*p.Form) < 1 {
errs = append(errs, errors.New("No data was received. Please submit from the profile page."))
}
for name, val := range *p.Form {
if fn, ok := stringValidator[name]; ok {
if err := fn(strings.Join(val, "")); err != nil {
errs = append(errs, err)
}
} else {
if fn, ok := stringsValidator[name]; ok {
if err := fn(val); err != nil {
errs = append(errs, err)
}
}
}
}
return Errors{errs}
}
const (
// Used for parsing the time
mmddyyyyForm = "01/02/2006" // we want the date sent in this format
yyyymmddForm = "2006-01-02" // However, HTML5 pages send the date in this format
)
var stringValidator map[string]func(string) error = map[string]func(string) error{
// parameter name : validator reference
"age": checkAge,
"birthday": checkDate,
"chineseName": checkChineseName,
"email": checkEmail,
"gender": checkGender,
"shirtsize": checkShirtSize,
"username": checkUsername,
}
var stringsValidator map[string]func([]string) error = map[string]func([]string) error{
// parameter name : validator reference
"sibling": checkSibling,
}
// Returns true if slices have a common element
func doSlicesIntersect(s1, s2 []string) bool {
if s1 == nil || s2 == nil {
return false
}
for _, str := range s1 {
if isElementInSlice(str, s2) {
return true
}
}
return false
}
func isElementInSlice(str string, sl []string) bool {
if sl == nil || str == "" {
return false
}
for _, v := range sl {
if v == str {
return true
}
}
return false
}
// Checks if all the characters are chinese characters. Won't check if empty.'
func checkChineseName(str string) error {
if str != "" {
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", strings.Trim(str, " ")); !m {
return errors.New("Please make sure that the chinese name only contains chinese characters.")
}
}
return nil
}
// Checks if a user name exist.
func checkUsername(str string) error {
if strings.Trim(str, " ") == "" {
return errors.New("Please enter a username.")
}
return nil
}
// Check if age is a number and between 13 and 130
func checkAge(str string) error {
age, err := strconv.Atoi(str)
if str == "" || err != nil {
return errors.New("Please enter a valid age.")
}
if age < 13 {
return errors.New("You must be at least 13 years of age to submit.")
}
if age > 130 {
return errors.New("You're too old to register, grandpa.")
}
return nil
}
func checkEmail(str string) error {
if m, err := regexp.MatchString(`^[^@]+@[^@]+$`, str); !m {
fmt.Println("err = ", err)
return errors.New("Please enter a valid email address.")
}
return nil
}
// Checks if a valid date was passed.
func checkDate(str string) error {
_, err := time.Parse(mmddyyyyForm, str)
if err != nil {
_, err = time.Parse(yyyymmddForm, str)
}
if str == "" || err != nil {
return errors.New("Please enter a valid Date.")
}
return nil
}
// Checks if the passed input is a known gender option
func checkGender(str string) error {
if str == "" {
return nil
}
siblings := []string{"m", "f", "na"}
if !isElementInSlice(str, siblings) {
return errors.New("Please select a valid gender.")
}
return nil
}
// Check if all the values are known options.
func checkSibling(strs []string) error {
if strs == nil || len(strs) < 1 {
return nil
}
siblings := []string{"m", "f"}
if siblings != nil && !doSlicesIntersect(siblings, strs) {
return errors.New("Please select a valid sibling")
}
return nil
}
// Checks if the shirt size is a known option.
func checkShirtSize(str string) error {
if str == "" {
return nil
}
shirts := []string{"s", "m", "l", "xl", "xxl"}
if !isElementInSlice(str, shirts) {
return errors.New("Please select a valid shirt size")
}
return nil
}

View File

@@ -0,0 +1,76 @@
// Example code for Chapter 5.2 from "Build Web Application with Golang"
// Purpose: Use SQL driver to perform simple CRUD operations.
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
const (
DB_USER = "user"
DB_PASSWORD = ""
DB_NAME = "test"
)
func main() {
dbSouce := fmt.Sprintf("%v:%v@/%v?charset=utf8", DB_USER, DB_PASSWORD, DB_NAME)
db, err := sql.Open("mysql", dbSouce)
checkErr(err)
defer db.Close()
fmt.Println("Inserting")
stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")
checkErr(err)
res, err := stmt.Exec("astaxie", "software developement", "2012-12-09")
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println("id of last inserted row =", id)
fmt.Println("Updating")
stmt, err = db.Prepare("update userinfo set username=? where uid=?")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", id)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect, "row(s) changed")
fmt.Println("Querying")
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username, department, created string
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println("uid | username | department | created")
fmt.Printf("%3v | %6v | %6v | %6v\n", uid, username, department, created)
}
fmt.Println("Deleting")
stmt, err = db.Prepare("delete from userinfo where uid=?")
checkErr(err)
res, err = stmt.Exec(id)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect, "row(s) changed")
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,12 @@
##Setup for `ch.5.2`
- Step 1) Install and run MySql
- Step 2) Create a user and database according to the constants in `main.go`
DB_USER = "user"
DB_PASSWORD = ""
DB_NAME = "test"
- Step 3) Create table `userinfo` located at `schema.sql`
- Step 4) Run `go get` to download and install the remote packages.
- Step 5) Execute the program with `go run main.go`

View File

@@ -0,0 +1,7 @@
CREATE TABLE `userinfo` (
`uid` INT(10) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(64) NULL DEFAULT NULL,
`departname` VARCHAR(64) NULL DEFAULT NULL,
`created` DATE NULL DEFAULT NULL,
PRIMARY KEY (`uid`)
);

Binary file not shown.

View File

@@ -0,0 +1,72 @@
// Example code for Chapter 5.3 from "Build Web Application with Golang"
// Purpose: Shows how to run simple CRUD operations using a sqlite driver
package main
import (
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
"time"
)
const DB_PATH = "./foo.db"
func main() {
db, err := sql.Open("sqlite3", DB_PATH)
checkErr(err)
defer db.Close()
fmt.Println("Inserting")
stmt, err := db.Prepare("INSERT INTO userinfo(username, department, created) values(?,?,?)")
checkErr(err)
res, err := stmt.Exec("astaxie", "software developement", time.Now().Format("2006-01-02"))
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println("id of last inserted row =", id)
fmt.Println("Updating")
stmt, err = db.Prepare("update userinfo set username=? where uid=?")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", id)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect, "row(s) changed")
fmt.Println("Querying")
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username, department, created string
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println("uid | username | department | created")
fmt.Printf("%3v | %6v | %8v | %6v\n", uid, username, department, created)
}
fmt.Println("Deleting")
stmt, err = db.Prepare("delete from userinfo where uid=?")
checkErr(err)
res, err = stmt.Exec(id)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect, "row(s) changed")
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,23 @@
## Set up for `ch.5.3`
- Step 1) Download and install sqlite 3.
- Step 2) Run `sqlite3 foo.db` to create a databased called `foo`.
- Step 3) Create the `userinfo` table in sqlite using `schema.sql`.
Read and run sql statements
sqlite> .read schema.sql
Show tables
sqlite> .tables
userinfo
- Step 4) Exit sqlite.
sqlite> .exit
- Step 5) Run `go get` to download and install remote packages.
- Step 6) Run the program with `go run main.go`

View File

@@ -0,0 +1,6 @@
CREATE TABLE `userinfo` (
`uid` INTEGER PRIMARY KEY AUTOINCREMENT,
`username` VARCHAR(64) NULL,
`department` VARCHAR(64) NULL,
`created` DATE NULL
);

View File

@@ -0,0 +1,77 @@
// Example code for Chapter 5.4 from "Build Web Application with Golang"
// Purpose: Show how to perform CRUD operations using a postgres driver
package main
import (
"database/sql"
"fmt"
_ "github.com/bmizerany/pq"
"time"
)
const (
DB_USER = "user"
DB_PASSWORD = ""
DB_NAME = "test"
)
func main() {
dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable",
DB_USER, DB_PASSWORD, DB_NAME)
db, err := sql.Open("postgres", dbinfo)
checkErr(err)
defer db.Close()
fmt.Println("# Inserting values")
var lastInsertId int
err = db.QueryRow("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) returning uid;",
"astaxie", "software developement", "2012-12-09").Scan(&lastInsertId)
checkErr(err)
fmt.Println("id of last inserted row =", lastInsertId)
fmt.Println("# Updating")
stmt, err := db.Prepare("update userinfo set username=$1 where uid=$2")
checkErr(err)
res, err := stmt.Exec("astaxieupdate", lastInsertId)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect, "row(s) changed")
fmt.Println("# Querying")
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username string
var department string
var created time.Time
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println("uid | username | department | created ")
fmt.Printf("%3v | %8v | %6v | %6v\n", uid, username, department, created)
}
fmt.Println("# Deleting")
stmt, err = db.Prepare("delete from userinfo where uid=$1")
checkErr(err)
res, err = stmt.Exec(lastInsertId)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect, "row(s) changed")
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,12 @@
##Setup for ch.5.4
- Step 1) Install and run Postgres
- Step 2) Create a user and database according to the constants in `main.go`
DB_USER = "user"
DB_PASSWORD = ""
DB_NAME = "test"
- Step 3) Create table `userinfo` located at `schema.sql`
- Step 4) Run `go get` to download and install the remote packages.
- Step 5) Execute the program with `go run main.go`

View File

@@ -0,0 +1,9 @@
CREATE TABLE userinfo
(
uid serial NOT NULL,
username character varying(100) NOT NULL,
departname character varying(500) NOT NULL,
Created date,
CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
)
WITH (OIDS=FALSE);

View File

@@ -0,0 +1,170 @@
// Example code for Chapter 5.5
// Purpose is to show to use BeeDB ORM for basic CRUD operations for sqlite3
package main
import (
"database/sql"
"fmt"
"github.com/astaxie/beedb"
_ "github.com/mattn/go-sqlite3"
"time"
)
var orm beedb.Model
type Userinfo struct {
Uid int `beedb:"PK"`
Username string
Department string
Created string
}
const DB_PATH = "./foo.db"
func checkError(err error) {
if err != nil {
panic(err)
}
}
func getTimeStamp() string {
return time.Now().Format("2006-01-02 15:04:05")
}
func insertUsingStruct() int64 {
fmt.Println("insertUsingStruct()")
var obj Userinfo
obj.Username = "Test Add User"
obj.Department = "Test Add Department"
obj.Created = getTimeStamp()
checkError(orm.Save(&obj))
fmt.Printf("%+v\n", obj)
return int64(obj.Uid)
}
func insertUsingMap() int64 {
fmt.Println("insertUsingMap()")
add := make(map[string]interface{})
add["username"] = "astaxie"
add["department"] = "cloud develop"
add["created"] = getTimeStamp()
id, err := orm.SetTable("userinfo").Insert(add)
checkError(err)
fmt.Println("Last row inserted id =", id)
return id
}
func getOneUserInfo(id int64) Userinfo {
fmt.Println("getOneUserInfo()")
var obj Userinfo
checkError(orm.Where("uid=?", id).Find(&obj))
return obj
}
func getAllUserInfo(id int64) []Userinfo {
fmt.Println("getAllUserInfo()")
var alluser []Userinfo
checkError(orm.Limit(10).Where("uid>?", id).FindAll(&alluser))
return alluser
}
func updateUserinfo(id int64) {
fmt.Println("updateUserinfo()")
var obj Userinfo
obj.Uid = int(id)
obj.Username = "Update Username"
obj.Department = "Update Department"
obj.Created = getTimeStamp()
checkError(orm.Save(&obj))
fmt.Printf("%+v\n", obj)
}
func updateUsingMap(id int64) {
fmt.Println("updateUsingMap()")
t := make(map[string]interface{})
t["username"] = "updateastaxie"
//update one
// id, err := orm.SetTable("userinfo").SetPK("uid").Where(2).Update(t)
//update batch
lastId, err := orm.SetTable("userinfo").Where("uid>?", id).Update(t)
checkError(err)
fmt.Println("Last row updated id =", lastId)
}
func getMapsFromSelect(id int64) []map[string][]byte {
fmt.Println("getMapsFromSelect()")
//Original SQL Backinfo resultsSlice []map[string][]byte
//default PrimaryKey id
c, err := orm.SetTable("userinfo").SetPK("uid").Where(id).Select("uid,username").FindMap()
checkError(err)
fmt.Printf("%+v\n", c)
return c
}
func groupby() {
fmt.Println("groupby()")
//Original SQL Group By
b, err := orm.SetTable("userinfo").GroupBy("username").Having("username='updateastaxie'").FindMap()
checkError(err)
fmt.Printf("%+v\n", b)
}
func joinTables(id int64) {
fmt.Println("joinTables()")
//Original SQL Join Table
a, err := orm.SetTable("userinfo").Join("LEFT", "userdetail", "userinfo.uid=userdetail.uid").Where("userinfo.uid=?", id).Select("userinfo.uid,userinfo.username,userdetail.profile").FindMap()
checkError(err)
fmt.Printf("%+v\n", a)
}
func deleteWithUserinfo(id int64) {
fmt.Println("deleteWithUserinfo()")
obj := getOneUserInfo(id)
id, err := orm.Delete(&obj)
checkError(err)
fmt.Println("Last row deleted id =", id)
}
func deleteRows() {
fmt.Println("deleteRows()")
//original SQL delete
id, err := orm.SetTable("userinfo").Where("uid>?", 2).DeleteRow()
checkError(err)
fmt.Println("Last row updated id =", id)
}
func deleteAllUserinfo(id int64) {
fmt.Println("deleteAllUserinfo()")
//delete all data
alluser := getAllUserInfo(id)
id, err := orm.DeleteAll(&alluser)
checkError(err)
fmt.Println("Last row updated id =", id)
}
func main() {
db, err := sql.Open("sqlite3", DB_PATH)
checkError(err)
orm = beedb.New(db)
var lastIdInserted int64
fmt.Println("Inserting")
lastIdInserted = insertUsingStruct()
insertUsingMap()
a := getOneUserInfo(lastIdInserted)
fmt.Println(a)
b := getAllUserInfo(lastIdInserted)
fmt.Println(b)
fmt.Println("Updating")
updateUserinfo(lastIdInserted)
updateUsingMap(lastIdInserted)
fmt.Println("Querying")
getMapsFromSelect(lastIdInserted)
groupby()
joinTables(lastIdInserted)
fmt.Println("Deleting")
deleteWithUserinfo(lastIdInserted)
deleteRows()
deleteAllUserinfo(lastIdInserted)
}

View File

@@ -0,0 +1,23 @@
## Set up for `ch.5.5`
- Step 1) Download and install sqlite 3.
- Step 2) Run `sqlite3 foo.db` to create a databased called `foo`.
- Step 3) Create the tables found in `schema.sql` in sqlite.
Read and run sql statements
sqlite> .read schema.sql
Show tables
sqlite> .tables
userinfo
userdetail
- Step 4) Exit sqlite.
sqlite> .exit
- Step 5) Run `go get` to download and install remote packages.
- Step 6) Run the program with `go run main.go`

View File

@@ -0,0 +1,12 @@
CREATE TABLE `userinfo` (
`uid` INTEGER PRIMARY KEY AUTOINCREMENT,
`username` VARCHAR(64) NULL,
`department` VARCHAR(64) NULL,
`created` DATE NULL
);
CREATE TABLE `userdetail` (
`uid` INT(10) NULL,
`intro` TEXT NULL,
`profile` TEXT NULL,
PRIMARY KEY (`uid`)
);

View File

@@ -0,0 +1,58 @@
// Example code for Chapter 5.6 from "Build Web Application with Golang"
// Purpose: Shows you have to perform basic CRUD operations for a mongodb driver.
package main
import (
"fmt"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
)
type Person struct {
Name string
Phone string
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
const (
DB_NAME = "test"
DB_COLLECTION = "people"
)
func main() {
session, err := mgo.Dial("localhost")
checkError(err)
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB(DB_NAME).C(DB_COLLECTION)
err = c.DropCollection()
checkError(err)
ale := Person{"Ale", "555-5555"}
cla := Person{"Cla", "555-1234"}
fmt.Println("Inserting")
err = c.Insert(&ale, &cla)
checkError(err)
fmt.Println("Updating")
ale.Phone = "555-0101"
err = c.Update(bson.M{"name": "Ale"}, &ale)
fmt.Println("Querying")
result := Person{}
err = c.Find(bson.M{"name": "Ale"}).One(&result)
checkError(err)
fmt.Println("Phone:", result.Phone)
fmt.Println("Deleting")
err = c.Remove(bson.M{"name": "Ale"})
checkError(err)
}

View File

@@ -0,0 +1,6 @@
##Setup for `ch.5.6` for MongoDB
- Step 1) Install and run MongoDB
- Step 2) Launch the MongoDB daemon (mongod) to start the server.
- Step 3) Run `go get` to download and install the remote packages.
- Step 4) Execute the program with `go run main.go`

View File

@@ -0,0 +1,60 @@
// Example code for Chapter 5.6 from "Build Web Application with Golang"
// Purpose: Shows you have to perform basic CRUD operations for a redis driver.
package main
import (
"fmt"
"github.com/astaxie/goredis"
)
func checkError(err error) {
if err != nil {
panic(err)
}
}
const (
DB_PORT = "9191"
DB_URL = "127.0.0.1"
)
func main() {
var client goredis.Client
// Set the default port in Redis
client.Addr = DB_URL + ":" + DB_PORT
// string manipulation
fmt.Println("Inserting")
err := client.Set("a", []byte("hello"))
checkError(err)
// list operation
vals := []string{"a", "b", "c", "d"}
for _, v := range vals {
err = client.Rpush("l", []byte(v))
checkError(err)
}
fmt.Println("Updating")
err = client.Set("a", []byte("a is for apple"))
checkError(err)
err = client.Rpush("l", []byte("e"))
checkError(err)
fmt.Println("Querying")
val, err := client.Get("a")
checkError(err)
fmt.Println(string(val))
dbvals, err := client.Lrange("l", 0, 4)
checkError(err)
for i, v := range dbvals {
println(i, ":", string(v))
}
fmt.Println("Deleting")
_, err = client.Del("l")
checkError(err)
_, err = client.Del("a")
checkError(err)
}

View File

@@ -0,0 +1,10 @@
##Setup for `ch.5.6` for Redis
- Step 1) Install and run Redis
- Step 2) Launch the Redis server matching the DB constants.
DB_PORT = "9191"
DB_URL = "127.0.0.1"
- Step 3) Run `go get` to download and install the remote packages.
- Step 4) Execute the program with `go run main.go`

View File

@@ -0,0 +1,12 @@
// Example code for Chapter 1.2 from "Build Web Application with Golang"
// Purpose: Shows how to create a simple package called `mymath`
// This package must be imported from another go file to run.
package mymath
func Sqrt(x float64) float64 {
z := 0.0
for i := 0; i < 1000; i++ {
z -= (z*z - x) / (2 * x)
}
return z
}