Full Code of shijuvar/go-recipes for AI

master 1ae756665620 cached
103 files
119.6 KB
37.9k tokens
362 symbols
1 requests
Download .txt
Repository: shijuvar/go-recipes
Branch: master
Commit: 1ae756665620
Files: 103
Total size: 119.6 KB

Directory structure:
gitextract_fqtkzqqz/

├── .gitignore
├── LICENSE
├── README.md
├── binarypkg/
│   ├── src/
│   │   └── github.com/
│   │       └── shijuvar/
│   │           └── binarypkg/
│   │               └── utils.go
│   └── utils.go
├── binarypkgdemo/
│   └── main.go
├── ch01/
│   ├── declarations/
│   │   ├── enum.go
│   │   ├── main.go
│   │   └── main1.go
│   ├── favorites/
│   │   └── main.go
│   ├── hello/
│   │   └── main.go
│   ├── lib/
│   │   ├── favorites.go
│   │   └── utils.go
│   ├── loop/
│   │   └── main.go
│   ├── strutils/
│   │   └── utils.go
│   ├── strutilsdemo/
│   │   └── main.go
│   ├── typeconv/
│   │   └── main.go
│   └── vetting/
│       └── main.go
├── ch02/
│   ├── arrays/
│   │   └── main.go
│   ├── defer/
│   │   ├── deferfunc.go
│   │   └── panicrecover.go
│   ├── functions/
│   │   ├── calc.go
│   │   ├── closures.go
│   │   ├── swap.go
│   │   └── variadic.go
│   ├── maps/
│   │   ├── main.go
│   │   └── sort_map.go
│   └── slices/
│       ├── append.go
│       ├── append_nilslice.go
│       ├── copy.go
│       ├── iterate.go
│       ├── main.go
│       └── slicing.go
├── ch03/
│   ├── ecommerce/
│   │   ├── main.go
│   │   └── models.go
│   ├── employee/
│   │   └── employee.go
│   ├── person.go
│   └── pointer/
│       └── main.go
├── ch04/
│   ├── channels/
│   │   └── main.go
│   ├── deadlock/
│   │   ├── main.go
│   │   └── main_deadlock.go
│   ├── mathtable/
│   │   └── main.go
│   ├── pipeline/
│   │   ├── main.go
│   │   └── main1.go
│   ├── select/
│   │   ├── context.go
│   │   └── main.go
│   ├── unbuffercounter/
│   │   ├── main.go
│   │   └── main1.go
│   └── worker/
│       └── main.go
├── ch05/
│   ├── archivetar/
│   │   └── main.go
│   ├── archivezip/
│   │   └── main.go
│   ├── cmdflags/
│   │   └── main.go
│   ├── flag/
│   │   └── main.go
│   ├── json/
│   │   └── main.go
│   ├── jsontag/
│   │   └── main.go
│   ├── log/
│   │   ├── logger.go
│   │   └── main.go
│   └── simplelog/
│       └── main.go
├── ch06/
│   ├── influx/
│   │   └── main.go
│   ├── mongo/
│   │   ├── bookmark_store.go
│   │   └── main.go
│   ├── postgres/
│   │   └── main.go
│   └── rethink/
│       ├── bookmark_store.go
│       └── main.go
├── ch07/
│   ├── bookmarkapi/
│   │   ├── common/
│   │   │   ├── auth.go
│   │   │   ├── bootstrapper.go
│   │   │   ├── config.json
│   │   │   ├── logger.go
│   │   │   ├── mongo_utils.go
│   │   │   └── utils.go
│   │   ├── controllers/
│   │   │   ├── bookmark_controller.go
│   │   │   ├── resources.go
│   │   │   └── user_controller.go
│   │   ├── keys/
│   │   │   ├── app.rsa
│   │   │   └── app.rsa.pub
│   │   ├── main.go
│   │   ├── model/
│   │   │   └── models.go
│   │   ├── routers/
│   │   │   ├── bookmark.go
│   │   │   ├── routers.go
│   │   │   └── user.go
│   │   └── store/
│   │       ├── bookmark_store.go
│   │       └── user_store.go
│   ├── customhandler/
│   │   └── main.go
│   ├── defaultservemux/
│   │   └── main.go
│   ├── handlefunc/
│   │   └── main.go
│   ├── handlerfunc/
│   │   └── main.go
│   ├── httpserver/
│   │   └── main.go
│   ├── middleware/
│   │   └── main.go
│   └── server/
│       └── main.go
├── ch08/
│   ├── calc/
│   │   ├── calc.go
│   │   └── calc_test.go
│   ├── httpbdd/
│   │   ├── controllers/
│   │   │   ├── controllers_suite_test.go
│   │   │   ├── user_controller.go
│   │   │   └── user_controller_test.go
│   │   ├── main.go
│   │   ├── model/
│   │   │   └── user.go
│   │   └── store/
│   │       └── user_store.go
│   └── httptest/
│       ├── main.go
│       └── main_test.go
└── grpc/
    ├── client/
    │   └── main.go
    ├── customer/
    │   ├── customer.pb.go
    │   └── customer.proto
    └── server/
        └── main.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

logs.txt
*.exe
*.test
*.prof
*.txt
debug
.vscode

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2016 Shiju Varghese

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Go Recipes
Code examples for the book "Go Recipes" by Apress.

# gokit
Check out [github.com/shijuvar/gokit](https://github.com/shijuvar/gokit) for further examples on Go. 

## Articles 
* [Building High Performance APIs In Go Using gRPC And Protocol Buffers](https://medium.com/@shijuvar/building-high-performance-apis-in-go-using-grpc-and-protocol-buffers-2eda5b80771b) 
* [Using Binary-Only Packages In Go](https://medium.com/@shijuvar/using-binary-only-packages-in-go-667bd7b123c8)



================================================
FILE: binarypkg/src/github.com/shijuvar/binarypkg/utils.go
================================================
//go:binary-only-package

package binarypkg


================================================
FILE: binarypkg/utils.go
================================================
package binarypkg

import "strings"

// ToUpperCase returns the string changed with upper case.
func ToUpperCase(s string) string {
	return strings.ToUpper(s)
}

// ToLowerCase returns the string changed with lower case.
func ToLowerCase(s string) string {
	return strings.ToLower(s)
}


================================================
FILE: binarypkgdemo/main.go
================================================
package main

import (
	"fmt"

	"github.com/shijuvar/go-recipes/binarypkg"
)

func main() {
	str := "Golang"
	// Convert to upper case
	fmt.Println("To Upper Case:", binarypkg.ToUpperCase(str))

	// Convert to lower case
	fmt.Println("To Lower Case:", binarypkg.ToLowerCase(str))

}


================================================
FILE: ch01/declarations/enum.go
================================================
package main

import "fmt"

const (
	// UNSPECIFIED logs nothing
	UNSPECIFIED Level = iota // 0 :
	// TRACE logs everything
	TRACE // 1
	// INFO logs Info, Warnings and Errors
	INFO // 2
	// WARNING logs Warning and Errors
	WARNING // 3
	// ERROR just logs Errors
	ERROR // 4
)

// Level holds the log level.
type Level int

// levels provides the string name of Level
var levels = [...]string{
	"UNSPECIFIED",
	"TRACE",
	"INFO",
	"WARNING",
	"ERROR",
}

// String returns the string value of level
func (l Level) String() string {
	return levels[l]
}

func main() {
	level := TRACE
	if level == TRACE {
		fmt.Println("TRACE")
	}
	level = INFO
	fmt.Println(level.String())
}


================================================
FILE: ch01/declarations/main.go
================================================
package main

import "fmt"

// Declare constant
const Title = "Person Details"

// Declare package variable
var Country = "USA"

func main() {
	fname, lname := "Shiju", "Varghese"
	age := 35
	// Print constant variable
	fmt.Println(Title)
	// Print local variables
	fmt.Println("First Name:", fname)
	fmt.Println("Last Name:", lname)
	fmt.Println("Age:", age)
	// Print package variable
	fmt.Println("Country:", Country)
}


================================================
FILE: ch01/declarations/main1.go
================================================
package main

import "fmt"

// Declare constant
const Title string = "Person Details"

// Declare package variable
var Country string = "USA"

func main() {
	var fname, lname string = "Shiju", "Varghese"
	var age int = 35
	// Print constant variable
	fmt.Println(Title)
	// Print local variables
	fmt.Println("First Name:", fname)
	fmt.Println("Last Name:", lname)
	fmt.Println("Age:", age)
	// Print package variable
	fmt.Println("Country:", Country)
}


================================================
FILE: ch01/favorites/main.go
================================================
package main

import (
	"fmt"

	fav "github.com/shijuvar/go-recipes/ch01/lib"
)

func main() {
	// Print default favorite packages
	fmt.Println("****** Default favorite packages ******\n")
	fav.PrintFavorites()
	// Add couple of favorites
	fav.Add("github.com/dgrijalva/jwt-go")
	fav.Add("github.com/onsi/ginkgo")
	fmt.Println("\n****** All favorite packages ******\n")
	fav.PrintFavorites()
	count := len(fav.GetAll())
	fmt.Printf("Total packages in the favorite list:%d", count)
}


================================================
FILE: ch01/hello/main.go
================================================
package main

import "fmt"

func main() {
	fmt.Println("Hello, World")
}


================================================
FILE: ch01/lib/favorites.go
================================================
package lib

// Stores favorites
var favorites []string

// Initialization logic for the package
func init() {
	favorites = make([]string, 3)
	favorites[0] = "github.com/gorilla/mux"
	favorites[1] = "github.com/codegangsta/negroni"
	favorites[2] = "gopkg.in/mgo.v2"
}

// Add a favorite into the in-memory collection
func Add(favorite string) {
	favorites = append(favorites, favorite)
}

// Returns all favorite
func GetAll() []string {
	return favorites
}


================================================
FILE: ch01/lib/utils.go
================================================
package lib

import (
	"fmt"
)

// Print all favorites
func PrintFavorites() {
	for _, v := range favorites {
		fmt.Println(v)
	}
}


================================================
FILE: ch01/loop/main.go
================================================
package main

import "fmt"

func main() {
	sum()
	sum1()
}
func sum() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}
func sum1() {
	sum := 1
	for sum < 50 {
		sum += sum
	}
	fmt.Println(sum)
}


================================================
FILE: ch01/strutils/utils.go
================================================
// Package strutils provides string utility functions
package strutils

import (
	"strings"
	"unicode"
)

// Returns the string changed with upper case.
func ToUpperCase(s string) string {
	return strings.ToUpper(s)
}

// Returns the string changed with lower case.
func ToLowerCase(s string) string {
	return strings.ToLower(s)
}

// Returns the string changed to upper case for its first letter.
func ToFirstUpper(s string) string {
	if len(s) < 1 { // if the empty string
		return s
	}
	// Trim the string
	t := strings.Trim(s, " ")
	// Convert all letters to lower case
	t = strings.ToLower(t)
	res := []rune(t)
	// Convert first letter to upper case
	res[0] = unicode.ToUpper(res[0])
	return string(res)
}


================================================
FILE: ch01/strutilsdemo/main.go
================================================
package main

import (
	"fmt"

	"github.com/shijuvar/go-recipes/ch01/strutils"
)

func main() {
	str1, str2 := "Golang", "gopher"
	// Convert to upper case
	fmt.Println("To Upper Case:", strutils.ToUpperCase(str1))

	// Convert to lower case
	fmt.Println("To Lower Case:", strutils.ToLowerCase(str1))

	// Convert first letter to upper case
	fmt.Println("To First Upper:", strutils.ToFirstUpper(str2))
}


================================================
FILE: ch01/typeconv/main.go
================================================
package main

import (
	"fmt"
	"reflect"
)

func main() {
	// type conversion: dealing with a type
	// The expression T(v) converts the value v to the type T
	i := 100
	f := float64(i)
	fmt.Println(reflect.TypeOf(f))
	// type assertion: dealing with an interface
	// A type assertion provides access to an interface value's underlying concrete value
	var x interface{} = 100 //float64(100)
	y := x.(float64)
	fmt.Println(reflect.TypeOf(y))
}


================================================
FILE: ch01/vetting/main.go
================================================
package main

import "fmt"

func main() {
	floatValue:=4.99
	fmt.Printf("The value is: %d",floatValue)
}


================================================
FILE: ch02/arrays/main.go
================================================
package main

import (
	"fmt"
)

func main() {
	// Declare arrays
	var x [5]int
	// Assign values at specific index
	x[0] = 5
	x[4] = 25
	fmt.Println("Value of x:", x)

	x[1] = 10
	x[2] = 15
	x[3] = 20
	fmt.Println("Value of x:", x)

	// Declare and initialize array with array literal
	y := [5]int{10, 20, 30, 40, 50}
	fmt.Println("Value of y:", y)
	fmt.Println("Length of y:", len(y))

	// Array literal with ...
	z := [...]int{10, 20, 30, 40, 50}
	fmt.Println("Value of z:", z)
	fmt.Println("Length of z:", len(z))

	// Initialize values at specific index with array literal
	langs := [4]string{0: "Go", 3: "Julia"}
	fmt.Println("Value of langs:", langs)
	// Assign values to remain positions
	langs[1] = "Rust"
	langs[2] = "Scala"

	// Iterate over the elements of array
	fmt.Println("Value of langs:", langs)
	fmt.Println("\nIterate over arrays\n")
	for i := 0; i < len(langs); i++ {
		fmt.Printf("langs[%d]:%s \n", i, langs[i])
	}
	fmt.Println("\n")

	// Iterate over the elements of array using range
	for k, v := range langs {
		fmt.Printf("langs[%d]:%s \n", k, v)
	}
	for k := range langs {
		fmt.Printf("Index:%d \n", k)
	}
	for _, v := range langs {
		fmt.Printf("Value:%s \n", v)
	}
}


================================================
FILE: ch02/defer/deferfunc.go
================================================
package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func ReadFile(filename string) ([]byte, error) {
	f, err := os.Open(filename)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	return ioutil.ReadAll(f)
}

func main() {
	f, _ := ReadFile("test.txt")
	fmt.Println("%s", f)
	fmt.Println(string(f))
}


================================================
FILE: ch02/defer/panicrecover.go
================================================
package main

import (
	"fmt"
)

func panicRecover() {

	defer fmt.Println("Deferred call - 1")
	defer func() {
		fmt.Println("Deferred call - 2")
		if e := recover(); e != nil {
			// e is the value passed to panic()
			fmt.Println("Recover with: ", e)
		}
	}()
	panic("Just panicking for the sake of example")
	fmt.Println("This will never be called")
}

func main() {
	fmt.Println("Starting to panic")
	panicRecover()
	fmt.Println("Program regains control after the panic recovery")
}


================================================
FILE: ch02/functions/calc.go
================================================
package main

import (
	"fmt"
)

func Add(x, y int) int {
	return x + y
}

func Subtract(x, y int) int {
	return x - y
}

func main() {
	x, y := 20, 10

	result := Add(x, y)
	fmt.Println("[Add]:", result)

	result = Subtract(x, y)
	fmt.Println("[Subtract]:", result)
}


================================================
FILE: ch02/functions/closures.go
================================================
package main

import (
	"fmt"
)

func SplitValues(f func(sum int) (int, int)) {
	x, y := f(35)
	fmt.Println(x, y)

	x, y = f(50)
	fmt.Println(x, y)
}

func main() {
	a, b := 5, 8
	fn := func(sum int) (int, int) {
		x := sum * a / b
		y := sum - x
		return x, y
	}

	// Passing function value as an argument to another function
	SplitValues(fn)

	// Calling the function value by providing argument
	x, y := fn(20)
	fmt.Println(x, y)
}


================================================
FILE: ch02/functions/swap.go
================================================
package main

import (
	"fmt"
)

func Swap(x, y string) (string, string) {
	return y, x
}

func main() {
	x, y := "Shiju", "Varghese"
	fmt.Println("Before Swap:", x, y)

	x, y = Swap(x, y)
	fmt.Println("After Swap:", x, y)
}


================================================
FILE: ch02/functions/variadic.go
================================================
package main

import (
	"fmt"
)

func Sum(nums ...int) int {
	total := 0
	for _, num := range nums {
		total += num
	}
	return total
}

func main() {
	// Providing four arguments
	total := Sum(1, 2, 3, 4)
	fmt.Println("The Sum is:", total)

	// Providing three arguments
	total = Sum(5, 7, 8)
	fmt.Println("The Sum is:", total)

	// Providing a Slice as an argument
	nums := []int{1, 2, 3, 4, 5}
	total = Sum(nums...)
	fmt.Println("The Sum is:", total)
}


================================================
FILE: ch02/maps/main.go
================================================
package main

import (
	"fmt"
)

func main() {
	// Declares a nil map
	var chapts map[int]string

	// Initialize map with make function
	chapts = make(map[int]string)

	// Add data as key/value pairs
	chapts[1] = "Beginning Go"
	chapts[2] = "Go Fundamentals"
	chapts[3] = "Structs and Interfaces"

	// Iterate over the elements of map using range
	for k, v := range chapts {
		fmt.Printf("Key: %d Value: %s\n", k, v)
	}

	// Declare and initialize map using map literal
	langs := map[string]string{
		"EL": "Greek",
		"EN": "English",
		"ES": "Spanish",
		"FR": "French",
		"HI": "Hindi",
	}

	// Delete an element
	delete(langs, "EL")

	// Lookout an element with key
	if lan, ok := langs["EL"]; ok {
		fmt.Println(lan)
	} else {
		fmt.Println("\nKey doesn't exists")
	}
	// Passing a map to function doesn't make a copy
	removeLan(langs, "HI")
	for k, v := range langs {
		fmt.Printf("Key: %s Value: %s\n", k, v)
	}
}
func removeLan(langs map[string]string, key string) {
	delete(langs, key)
}


================================================
FILE: ch02/maps/sort_map.go
================================================
package main

import (
	"fmt"
	"sort"
)

func main() {
	// Initialize map with make function
	chapts := make(map[int]string)

	// Add data as key/value pairs
	chapts[1] = "Beginning Go"
	chapts[2] = "Go Fundamentals"
	chapts[3] = "Structs and Interfaces"
	for k, v := range chapts {
		fmt.Println(k, v)
	}

	// Slice for specifying the order of the map
	var keys []int
	// Appending keys of the map
	for k := range chapts {
		keys = append(keys, k)
	}
	// Ints sorts a slice of ints in increasing order.
	sort.Ints(keys)
	// Iterate over the map with an order
	for _, k := range keys {
		fmt.Println("Key:", k, "Value:", chapts[k])
	}
}


================================================
FILE: ch02/slices/append.go
================================================
package main

import (
	"fmt"
)

func main() {
	x := make([]int, 2, 5)
	x[0] = 10
	x[1] = 20
	fmt.Println("Slice x:", x)
	fmt.Printf("Length is %d Capacity is %d\n", len(x), cap(x))
	// Create a bigger slice
	x = append(x, 30, 40, 50)
	fmt.Println("Slice x after appending data:", x)
	fmt.Printf("Length is %d Capacity is %d\n", len(x), cap(x))

	x = append(x, 60, 70, 80)
	fmt.Println("Slice x after appending data for the second time:", x)
	fmt.Printf("Length is %d Capacity is %d\n", len(x), cap(x))

}


================================================
FILE: ch02/slices/append_nilslice.go
================================================
package main

import "fmt"

func main() {
	// Declare a nil slice
	var x []int
	fmt.Println(x, len(x), cap(x))
	x = append(x, 10, 20, 30)
	fmt.Println("Slice x after appending data:", x)
}


================================================
FILE: ch02/slices/copy.go
================================================
package main

import (
	"fmt"
)

func main() {
	x := []int{10, 20, 30}
	fmt.Printf("[Slice:x] Length is %d Capacity is %d\n", len(x), cap(x))
	// Create a bigger slice
	y := make([]int, 5, 10)
	copy(y, x)
	fmt.Printf("[Slice:y] Length is %d Capacity is %d\n", len(y), cap(y))
	fmt.Println("Slice y after copying:", y)
	y[3] = 40
	y[4] = 50
	fmt.Println("Slice y after adding elements:", y)
}


================================================
FILE: ch02/slices/iterate.go
================================================
package main

import (
	"fmt"
)

func main() {
	x := []int{10, 20, 30, 40, 50}
	for k, v := range x {
		fmt.Printf("x[%d]: %d\n", k, v)
	}
}


================================================
FILE: ch02/slices/main.go
================================================
package main

import (
	"fmt"
)

func main() {
	x := make([]int, 3, 5)
	x[0] = 10
	x[1] = 20
	x[2] = 30
	fmt.Println(x)
	fmt.Println(len(x))
	fmt.Println(cap(x))

	y := make([]int, 3)
	y[0] = 10
	y[1] = 20
	y[2] = 30
	fmt.Println(y)
	fmt.Println(len(y))
	fmt.Println(cap(y))

	z := []int{10, 20, 30}
	fmt.Println(len(z))
	fmt.Println(cap(z))

	z1 := []int{0: 10, 2: 30}
	fmt.Println(len(z1))
	fmt.Println(cap(z1))

	x1 := []int{10, 20, 30}
	y1 := append(x1, 40, 50)
	fmt.Println(x1, y1)
}


================================================
FILE: ch02/slices/slicing.go
================================================
package main

import (
	"fmt"
)

func main() {
	x := []int{10, 20, 30, 40, 50}
	y := x[1:3]
	fmt.Println("y:", y)
	fmt.Println(len(y))
	fmt.Println(cap(y))

	z := x[:3]
	fmt.Println("z:", z)
	fmt.Println(len(z))
	fmt.Println(cap(z))
	x1 := x[:]
	fmt.Println("x1:", x1)
	fmt.Println(len(x1))
	fmt.Println(cap(x1))

	x1[4] = 75
	fmt.Println("x:", x)
	fmt.Println("x1:", x1)

}


================================================
FILE: ch03/ecommerce/main.go
================================================
package main

import (
	"fmt"
	"time"
)

func main() {
	order := &Order{
		Id: 1001,
		Customer: Customer{
			FirstName: "Alex",
			LastName:  "John",
			Email:     "alex@email.com",
			Phone:     "732-757-2923",
			Addresses: []Address{
				Address{
					Street:            "1 Mission Street",
					City:              "San Francisco",
					State:             "CA",
					Zip:               "94105",
					IsShippingAddress: true,
				},
				Address{
					Street: "49 Stevenson Street",
					City:   "San Francisco",
					State:  "CA",
					Zip:    "94105",
				},
			},
		},
		Status:   "Placed",
		PlacedOn: time.Date(2016, time.April, 10, 0, 0, 0, 0, time.UTC),
		OrderItems: []OrderItem{
			OrderItem{
				Product: Product{
					Code:        "knd100",
					Name:        "Kindle Voyage",
					Description: "Kindle Voyage Wifi, 6 High-Resolution Display",
					UnitPrice:   220,
				},
				Quantity: 1,
			},
			OrderItem{
				Product: Product{
					Code:        "fint101",
					Name:        "Kindle Case",
					Description: "Fintie Kindle Voyage SmartShell Case",
					UnitPrice:   10,
				},
				Quantity: 2,
			},
		},
	}

	fmt.Println(order.ToString())
	// Change Order status
	order.ChangeStatus("Processing")
	fmt.Println("\n")
	fmt.Println(order.ToString())
}


================================================
FILE: ch03/ecommerce/models.go
================================================
package main

import (
	"fmt"
	"time"
)

type Address struct {
	Street, City, State, Zip string
	IsShippingAddress        bool
}

type Customer struct {
	FirstName, LastName, Email, Phone string
	Addresses                         []Address
}

func (c Customer) ToString() string {
	return fmt.Sprintf("Customer: %s %s, Email:%s", c.FirstName, c.LastName, c.Email)
}
func (c Customer) ShippingAddress() string {
	for _, v := range c.Addresses {
		if v.IsShippingAddress == true {
			return fmt.Sprintf("%s, %s, %s, Zip - %s", v.Street, v.City, v.State, v.Zip)
		}
	}
	return ""
}

type Order struct {
	Id int
	Customer
	PlacedOn   time.Time
	Status     string
	OrderItems []OrderItem
}

func (o *Order) GrandTotal() float64 {
	var total float64
	for _, v := range o.OrderItems {
		total += v.Total()
	}
	return total
}
func (o *Order) ToString() string {
	var orderStr string
	orderStr = fmt.Sprintf("Order#:%d, OrderDate:%s, Status:%s, Grand Total:%f\n", o.Id, o.PlacedOn, o.Status, o.GrandTotal())
	orderStr += o.Customer.ToString()
	orderStr += fmt.Sprintf("\nOrder Items:")
	for _, v := range o.OrderItems {
		orderStr += fmt.Sprintf("\n")
		orderStr += v.ToString()
	}
	orderStr += fmt.Sprintf("\nShipping Address:")
	orderStr += o.Customer.ShippingAddress()
	return orderStr
}
func (o *Order) ChangeStatus(newStatus string) {
	o.Status = newStatus
}

type OrderItem struct {
	Product
	Quantity int
}

func (item OrderItem) Total() float64 {
	return float64(item.Quantity) * item.Product.UnitPrice
}
func (item OrderItem) ToString() string {
	itemStr := fmt.Sprintf("Code:%s, Product:%s -- %s, UnitPrice:%f, Quantity:%d, Total:%f",
		item.Product.Code, item.Product.Name, item.Product.Description, item.Product.UnitPrice, item.Quantity, item.Total())
	return itemStr

}

type Product struct {
	Code, Name, Description string
	UnitPrice               float64
}


================================================
FILE: ch03/employee/employee.go
================================================
// Example program with Interface, Composition and Method Overriding
package main

import (
	"fmt"
	"time"
)

type TeamMember interface {
	PrintName()
	PrintDetails()
}

type Employee struct {
	FirstName, LastName string
	Dob                 time.Time
	JobTitle, Location  string
}

func (e Employee) PrintName() {
	fmt.Printf("\n%s %s\n", e.FirstName, e.LastName)
}

func (e Employee) PrintDetails() {
	fmt.Printf("Date of Birth: %s, Job: %s, Location: %s\n", e.Dob.String(), e.JobTitle, e.Location)
}

type Developer struct {
	Employee //type embedding for composition
	Skills   []string
}

// Overrides the PrintDetails
func (d Developer) PrintDetails() {
	// Call Employee PrintDetails
	d.Employee.PrintDetails()
	fmt.Println("Technical Skills:")
	for _, v := range d.Skills {
		fmt.Println(v)
	}
}

type Manager struct {
	Employee  //type embedding for composition
	Projects  []string
	Locations []string
}

// Overrides the PrintDetails
func (m Manager) PrintDetails() {
	// Call Employee PrintDetails
	m.Employee.PrintDetails()
	fmt.Println("Projects:")
	for _, v := range m.Projects {
		fmt.Println(v)
	}
	fmt.Println("Managing teams for the locations:")
	for _, v := range m.Locations {
		fmt.Println(v)
	}
}

type Team struct {
	Name, Description string
	TeamMembers       []TeamMember
}

func (t Team) PrintTeamDetails() {
	fmt.Printf("Team: %s  - %s\n", t.Name, t.Description)
	fmt.Println("Details of the team members:")
	for _, v := range t.TeamMembers {
		v.PrintName()
		v.PrintDetails()
	}
}

func main() {
	steve := Developer{
		Employee: Employee{
			FirstName: "Steve",
			LastName:  "John",
			Dob:       time.Date(1990, time.February, 17, 0, 0, 0, 0, time.UTC),
			JobTitle:  "Software Engineer",
			Location:  "San Fancisco",
		},
		Skills: []string{"Go", "Docker", "Kubernetes"},
	}
	irene := Developer{
		Employee: Employee{
			FirstName: "Irene",
			LastName:  "Rose",
			Dob:       time.Date(1991, time.January, 13, 0, 0, 0, 0, time.UTC),
			JobTitle:  "Software Engineer",
			Location:  "Santa Clara",
		},
		Skills: []string{"Go", "MongoDB"},
	}
	alex := Manager{
		Employee: Employee{
			FirstName: "Alex",
			LastName:  "Williams",
			Dob:       time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
			JobTitle:  "Program Manger",
			Location:  "Santa Clara",
		},
		Projects:  []string{"CRM", "e-Commerce"},
		Locations: []string{"San Fancisco", "Santa Clara"},
	}

	// Create team
	team := Team{
		"Go",
		"Golang Engineering Team",
		[]TeamMember{steve, irene, alex},
	}
	// Get details of Team
	team.PrintTeamDetails()
}


================================================
FILE: ch03/person.go
================================================
// Person struct with methods of pointer receiver

package main

import (
	"fmt"
	"time"
)

// Person struct
type Person struct {
	FirstName, LastName string
	Dob                 time.Time
	Email, Location     string
}

// PrintName prints the name of the Person
func (p Person) PrintName() {
	fmt.Printf("\n%s %s\n", p.FirstName, p.LastName)
}

// PrintDetails prints the details of Person
func (p Person) PrintDetails() {
	fmt.Printf("[Date of Birth: %s, Email: %s, Location: %s ]\n", p.Dob.String(), p.Email, p.Location)
}

func main() {
	/*
		       // Declare a Person variable using var
				var p Person
				// Assign values to fields
				p.FirstName="Shiju"
				p.LastName="Varghese"
				p.Dob= time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC)
				p.Email="shiju@email.com"
				p.Location= "Kochi"

				// Declare a Person variable and initialize values using Struct literal
				p := Person{
					"Shiju",
					"Varghese",
					time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
					"shiju@email.com",
					"Kochi",
				}

	*/
	p := Person{
		FirstName: "Shiju",
		LastName:  "Varghese",
		Dob:       time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
		Email:     "shiju@email.com",
		Location:  "Kochi",
	}
	p.PrintName()
	p.PrintDetails()

}


================================================
FILE: ch03/pointer/main.go
================================================
// Person struct with methods of pointer receiver

package main

import (
	"fmt"
	"time"
)

type Person struct {
	FirstName, LastName string
	Dob                 time.Time
	Email, Location     string
}

//A person method with pointer receiver
func (p *Person) PrintName() {
	fmt.Printf("\n%s %s\n", p.FirstName, p.LastName)
}

//A person method with pointer receiver
func (p *Person) PrintDetails() {
	fmt.Printf("[Date of Birth: %s, Email: %s, Location: %s ]\n", p.Dob.String(), p.Email, p.Location)
}

//A person method with pointer receiver
func (p *Person) ChangeLocation(newLocation string) {
	p.Location = newLocation
}
func main() {
	p := &Person{
		"Shiju",
		"Varghese",
		time.Date(1979, time.February, 17, 0, 0, 0, 0, time.UTC),
		"shiju@email.com",
		"Kochi",
	}
	p.ChangeLocation("Santa Clara")
	p.PrintName()
	p.PrintDetails()

}


================================================
FILE: ch04/channels/main.go
================================================
package main

import (
	"fmt"
)

func main() {
	// Declare a unbuffered channel
	counter := make(chan int)
	// Creates a buffered channel with capacity of 3
	nums := make(chan int, 3)
	go func() {
		// Send value to the unbuffered channel
		counter <- 1
		close(counter) // Closes the channel
	}()

	go func() {
		// Send values to the buffered channel
		nums <- 10
		nums <- 30
		nums <- 50
	}()
	// Read the value from unbuffered channel
	fmt.Println(<-counter)
	val, ok := <-counter // Trying to read from closed channel
	if ok {
		fmt.Println(val) // This won't execute
	}
	// Read the 3 buffered values from the buffered channel
	fmt.Println(<-nums)
	fmt.Println(<-nums)
	fmt.Println(<-nums)
	close(nums) // Closes the channel
}


================================================
FILE: ch04/deadlock/main.go
================================================
package main

import (
	"fmt"
)

func main() {
	// Declare a unbuffered channel
	counter := make(chan int)
	// Perform send operation by launching new goroutine
	go func() {
		counter <- 10
	}()
	fmt.Println(<-counter) // Receive operation from the channel
}


================================================
FILE: ch04/deadlock/main_deadlock.go
================================================
package main

import (
	"fmt"
)

func main() {
	// Declare a unbuffered channel
	counter := make(chan int)
	// This will create a deadlock
	counter <- 10          // Send operation to a channel from main goroutine
	fmt.Println(<-counter) // Receive operation from the channel
}


================================================
FILE: ch04/mathtable/main.go
================================================
// This sample program demonstrates how to create goroutines
package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

// WaitGroup is used to wait for the program to finish goroutines.
var wg sync.WaitGroup

func main() {

	// Add a count of two, one for each goroutine.
	wg.Add(2)

	fmt.Println("Start Goroutines")
	// Launch functions as goroutines
	go addTable()
	go multiTable()
	// Wait for the goroutines to finish.
	fmt.Println("Waiting To Finish")
	wg.Wait()
	fmt.Println("\nTerminating Program")
}

func addTable() {
	// Schedule the call to WaitGroup's Done to tell goroutine is completed.
	defer wg.Done()
	for i := 1; i <= 10; i++ {
		sleep := rand.Int63n(1000)
		time.Sleep(time.Duration(sleep) * time.Millisecond)
		fmt.Println("Addition Table for:", i)
		for j := 1; j <= 10; j++ {
			//res = i + j
			fmt.Printf("%d+%d=%d\t", i, j, i+j)
		}
		fmt.Println("\n")
	}
}
func multiTable() {
	// Schedule the call to WaitGroup's Done to tell goroutine is completed.
	defer wg.Done()
	for i := 1; i <= 10; i++ {
		sleep := rand.Int63n(1000)
		time.Sleep(time.Duration(sleep) * time.Millisecond)
		fmt.Println("Multiplication Table for:", i)
		for j := 1; j <= 10; j++ {
			//res = i + j
			fmt.Printf("%d*%d=%d\t", i, j, i*j)
		}
		fmt.Println("\n")
	}
}


================================================
FILE: ch04/pipeline/main.go
================================================
package main

import (
	"fmt"
	"math"
	"math/rand"
	"sync"
)

type fibvalue struct {
	input, value int
}

var wg sync.WaitGroup

func randomCounter(out chan<- int) {
	defer wg.Done()
	var random int
	for x := 0; x < 10; x++ {
		random = rand.Intn(50)
		out <- random
	}
	close(out)
}

func generateFibonacci(out chan<- fibvalue, in <-chan int) {
	defer wg.Done()
	var input float64
	for v := range in {
		input = float64(v)
		// Fibonacci using Binet's formula
		Phi := (1 + math.Sqrt(5)) / 2
		phi := (1 - math.Sqrt(5)) / 2
		result := (math.Pow(Phi, input) - math.Pow(phi, input)) / math.Sqrt(5)
		out <- fibvalue{
			input: v,
			value: int(result),
		}
	}
	close(out)
}

func printFibonacci(in <-chan fibvalue) {
	defer wg.Done()
	for v := range in {
		fmt.Printf("Fibonacci value of %d is %d\n", v.input, v.value)
	}
}

func main() {
	// Add 3 into WaitGroup Counter
	wg.Add(3)
	// Declare Channels
	randoms := make(chan int)
	fibs := make(chan fibvalue)
	// Launching 3 goroutines
	go randomCounter(randoms)
	go generateFibonacci(fibs, randoms)
	go printFibonacci(fibs)
	// Wait for completing all goroutines
	wg.Wait()
}


================================================
FILE: ch04/pipeline/main1.go
================================================
package main

import (
	"fmt"
	"math"
	"math/rand"
	"sync"
)

type fibvalue struct {
	input, value int
}

var wg sync.WaitGroup

// Generates random values
func randomCounter(out chan int) {
	defer wg.Done()
	var random int
	for x := 0; x < 10; x++ {
		random = rand.Intn(50)
		out <- random
	}
	close(out)
}

// Produces fibonacci values of inputs provided by randomCounter
func generateFibonacci(out chan fibvalue, in chan int) {
	defer wg.Done()
	var input float64
	for v := range in {
		input = float64(v)
		// Fibonacci using Binet's formula
		Phi := (1 + math.Sqrt(5)) / 2
		phi := (1 - math.Sqrt(5)) / 2
		result := (math.Pow(Phi, input) - math.Pow(phi, input)) / math.Sqrt(5)
		out <- fibvalue{
			input: v,
			value: int(result),
		}
	}
	close(out)
}

// Print fibonacci values generated by generateFibonacci
func printFibonacci(in chan fibvalue) {
	defer wg.Done()
	for v := range in {
		fmt.Printf("Fibonacci value of %d is %d\n", v.input, v.value)
	}
}

func main() {
	// Add 3 into WaitGroup Counter
	wg.Add(3)
	// Declare Channels
	randoms := make(chan int)
	fibs := make(chan fibvalue)
	// Launching 3 goroutines
	go randomCounter(randoms)           // First stage of pipeline
	go generateFibonacci(fibs, randoms) // Second stage of pipeline
	go printFibonacci(fibs)             // Third stage of pipeline
	// Wait for completing all goroutines
	wg.Wait()
}


================================================
FILE: ch04/select/context.go
================================================
package main

import (
	"context"
	"fmt"
)

func generateValues(ctx context.Context, counter chan int) {
	n := 1
	for {
		select {
		case <-ctx.Done():
			return
		case counter <- n:
			n++
		}
	}
}

func main() {
	// WithCancel returns a copy of parent with a new Done channel. The returned
	// context's Done channel is closed when the returned cancel function is called
	// or when the parent context's Done channel is closed, whichever happens first.
	//
	// Canceling this context releases resources associated with it, so code should
	// call cancel as soon as the operations running in this Context complete.
	ctx, cancel := context.WithCancel(context.Background())
	// ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	counter := make(chan int)
	defer cancel()
	go generateValues(ctx, counter)
	for n := range counter {
		fmt.Println(n)
		if n == 10 {
			cancel()
			break
		}
	}
}


================================================
FILE: ch04/select/main.go
================================================
package main

import (
	"fmt"
	"math"
	"math/rand"
	"sync"
)

type (
	fibvalue struct {
		input, value int
	}
	squarevalue struct {
		input, value int
	}
)

func generateSquare(sqrs chan<- squarevalue) {
	defer wg.Done()
	for i := 1; i <= 10; i++ {
		num := rand.Intn(50)
		sqrs <- squarevalue{
			input: num,
			value: num * num,
		}
	}
}
func generateFibonacci(fibs chan<- fibvalue) {
	defer wg.Done()
	for i := 1; i <= 10; i++ {
		num := float64(rand.Intn(50))
		// Fibonacci using Binet's formula
		Phi := (1 + math.Sqrt(5)) / 2
		phi := (1 - math.Sqrt(5)) / 2
		result := (math.Pow(Phi, num) - math.Pow(phi, num)) / math.Sqrt(5)
		fibs <- fibvalue{
			input: int(num),
			value: int(result),
		}
	}
}
func printValues(fibs <-chan fibvalue, sqrs <-chan squarevalue) {
	defer wg.Done()
	for i := 1; i <= 20; i++ {
		select {
		case fib := <-fibs:
			fmt.Printf("Fibonacci value of %d is %d\n", fib.input, fib.value)
		case sqr := <-sqrs:
			fmt.Printf("Square value of %d is %d\n", sqr.input, sqr.value)
		}
	}
}

// wg is used to wait for the program to finish.
var wg sync.WaitGroup

func main() {
	wg.Add(3)
	// Create Channels
	fibs := make(chan fibvalue)
	sqrs := make(chan squarevalue)
	// Launching 3 goroutines
	go generateFibonacci(fibs)
	go generateSquare(sqrs)
	go printValues(fibs, sqrs)
	// Wait for completing all goroutines
	wg.Wait()
}


================================================
FILE: ch04/unbuffercounter/main.go
================================================
// Example program with unbuffered channel
package main

import (
	"fmt"
	"sync"
)

// wg is used to wait for the program to finish.
var wg sync.WaitGroup

func main() {

	count := make(chan int)
	// Add a count of two, one for each goroutine.
	wg.Add(2)

	fmt.Println("Start Goroutines")
	// Launch a goroutine with label "Goroutine-1"
	go printCounts("Goroutine-1", count)
	// Launch a goroutine with label "Goroutine-2"
	go printCounts("Goroutine-2", count)
	fmt.Println("Communication of channel begins")
	count <- 1
	// Wait for the goroutines to finish.
	fmt.Println("Waiting To Finish")
	wg.Wait()
	fmt.Println("\nTerminating the Program")
}

func printCounts(label string, count chan int) {
	// Schedule the call to WaitGroup's Done to tell goroutine is completed.
	defer wg.Done()
	for val := range count {
		fmt.Printf("Count: %d received from %s \n", val, label)
		if val == 10 {
			fmt.Printf("Channel Closed from %s \n", label)
			// Close the channel
			close(count)
			return
		}
		val++
		// Send count back to the other goroutine.
		count <- val
	}
}


================================================
FILE: ch04/unbuffercounter/main1.go
================================================
// Example program with unbuffered channel
package main

import (
	"fmt"
	"sync"
)

// wg is used to wait for the program to finish.
var wg sync.WaitGroup

func main() {

	count := make(chan int)
	// Add a count of two, one for each goroutine.
	wg.Add(2)

	fmt.Println("Start Goroutines")
	// Launch a goroutine with label "Goroutine-1"
	go printCounts("Goroutine-1", count)
	// Launch a goroutine with label "Goroutine-2"
	go printCounts("Goroutine-2", count)
	fmt.Println("Communication of channel begins")
	count <- 1
	// Wait for the goroutines to finish.
	fmt.Println("Waiting To Finish")
	wg.Wait()
	fmt.Println("\nTerminating the Program")
}

func printCounts(label string, count chan int) {
	// Schedule the call to WaitGroup's Done to tell goroutine is completed.
	defer wg.Done()
	for {
		// Receives message from Channel
		val, ok := <-count
		if !ok {
			fmt.Println("Channel was closed")
			return
		}
		fmt.Printf("Count: %d received from %s \n", val, label)
		if val == 10 {
			fmt.Printf("Channel Closed from %s \n", label)
			// Close the channel
			close(count)
			return
		}
		val++
		// Send count back to the other goroutine.
		count <- val
	}
}


================================================
FILE: ch04/worker/main.go
================================================
// This sample program demonstrates how to use a buffered
// channel to work on multiple tasks with a predefined number
// of goroutines.
package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

type Task struct {
	Id        int
	JobId     int
	Status    string
	CreatedOn time.Time
}

func (t *Task) Run() {

	sleep := rand.Int63n(1000)
	// Delaying the execution for the sake of example
	time.Sleep(time.Duration(sleep) * time.Millisecond)
	t.Status = "Completed"
}

// wg is used to wait for the program to finish.
var wg sync.WaitGroup

const noOfWorkers = 3

// main is the entry point for all Go programs.
func main() {
	// Create a buffered channel to manage the task queue.
	taskQueue := make(chan *Task, 10)

	// Launch goroutines to handle the work.
	// The worker process is distributing with the value of noOfWorkers.
	wg.Add(noOfWorkers)
	for gr := 1; gr <= noOfWorkers; gr++ {
		go worker(taskQueue, gr)
	}

	// Add Tasks into Buffered channel.
	for i := 1; i <= 10; i++ {
		taskQueue <- &Task{
			Id:        i,
			JobId:     100 + i,
			CreatedOn: time.Now(),
		}
	}

	// Close the channel
	close(taskQueue)

	// Wait for all the work to get done.
	wg.Wait()
}

// worker is launched as a goroutine to process Tasks from
// the buffered channel.
func worker(taskQueue <-chan *Task, workerId int) {
	// Schedule the call to Done method of WaitGroup.
	defer wg.Done()
	for v := range taskQueue {
		fmt.Printf("Worker%d: received request for Task:%d - Job:%d\n", workerId, v.Id, v.JobId)
		v.Run()
		// Display we finished the work.
		fmt.Printf("Worker%d: Status:%s for Task:%d - Job:%d\n", workerId, v.Status, v.Id, v.JobId)
	}
}


================================================
FILE: ch05/archivetar/main.go
================================================
package main

import (
	"archive/tar"
	"fmt"
	"io"
	"log"
	"os"
)

// addToArchive writes a given file into a .tar file
// Returns nill if the operation is succeeded
func addToArchive(filename string, tw *tar.Writer) error {
	// Open the file to archive into tar file.
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	// Get the FileInfo struct that describe the file.
	fileinfo, err := file.Stat()
	// Create a pointer to tar.Header struct
	hdr := &tar.Header{
		ModTime: fileinfo.ModTime(),            // modified time
		Name:    filename,                      // name of header
		Size:    fileinfo.Size(),               // length in bytes
		Mode:    int64(fileinfo.Mode().Perm()), // permission and mode bits
	}
	// WriteHeader writes tar.Header and prepares to accept the file's contents.
	if err := tw.WriteHeader(hdr); err != nil {
		return err
	}
	// Write the file contents to the tar file.
	copied, err := io.Copy(tw, file)
	if err != nil {
		return err
	}
	// Check the size of copied file with the source file.
	if copied < fileinfo.Size() {
		return fmt.Errorf("Size of the copied file doesn't match with source file %s: %s", filename, err)
	}
	return nil
}

// archiveFiles archives a group of given files into a tar file.
func archiveFiles(files []string, archive string) error {
	// Flags for open the tar file.
	flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC
	// Open the tar file
	file, err := os.OpenFile(archive, flags, 0644)
	if err != nil {
		return err
	}
	defer file.Close()
	// Create a new Writer writing to given file object.
	// Writer provides sequential writing of a tar archive in POSIX.1 format.
	tw := tar.NewWriter(file)
	defer tw.Close()
	// Iterate through the files to write each file into the tar file.
	for _, filename := range files {
		// Write the file into tar file.
		if err := addToArchive(filename, tw); err != nil {
			return err
		}
	}
	return nil
}

// readArchive reads the file contents from tar file.
func readArchive(archive string) error {
	// Open the tar archive file.
	file, err := os.Open(archive)
	if err != nil {
		return err
	}
	defer file.Close()
	// Create the tar.Reader to read the tar archive.
	// A Reader provides sequential access to the contents of a tar archive.
	tr := tar.NewReader(file)
	// Iterate through the files in the tar archive.
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			// End of tar archive
			fmt.Println("end")
			break
		}
		if err != nil {
			return err
		}
		size := hdr.Size
		contents := make([]byte, size)
		read, err := io.ReadFull(tr, contents)
		// Check the size of file contents
		if int64(read) != size {
			return fmt.Errorf("Size of the opened file doesn't match with the file %s", hdr.Name)
		}
		// hdr.Name returns the file name.
		fmt.Printf("Contents of the file %s:\n", hdr.Name)
		// Writing the file contents into Stdout.
		fmt.Fprintf(os.Stdout, "\n%s", contents)
	}
	return nil
}

func main() {
	// Name of the tar file
	archive := "source.tar"
	// Files to be archived in tar format
	files := []string{"main.go", "readme.txt"}
	// Archive files into tar format
	err := archiveFiles(files, archive)
	if err != nil {
		log.Fatalf("Error while writing to tar file:%s", err)
	}
	// Archiving is sucsess.
	fmt.Println("The tar file source.tar has been created")
	// Read the file contents of tar file
	err = readArchive(archive)
	if err != nil {
		log.Fatalf("Error while reading the tar file:%s", err)
	}
}


================================================
FILE: ch05/archivezip/main.go
================================================
package main

import (
	"archive/zip"
	"fmt"
	"io"
	"log"
	"os"
)

// addToArchive writes a given file into a zip file.
func addToArchive(filename string, zw *zip.Writer) error {
	// Open the given file to archive into a zip file.
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	// Create adds a file to the zip file using the given name/
	// Create returns a io.Writer to which the file contents should be written.
	wr, err := zw.Create(filename)
	if err != nil {
		return err
	}
	// Write the file contents to the zip file.
	if _, err := io.Copy(wr, file); err != nil {
		return err
	}
	return nil
}

// archiveFiles archives a group of given files into a zip file.
func archiveFiles(files []string, archive string) error {
	flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC
	// Open the tar file
	file, err := os.OpenFile(archive, flags, 0644)
	if err != nil {
		return err
	}
	defer file.Close()
	// Create zip.Writer that implements a zip file writer.
	zw := zip.NewWriter(file)
	defer zw.Close()
	// Iterate through the files to write each file into the zip file.
	for _, filename := range files {
		// Write the file into tar file.
		if err := addToArchive(filename, zw); err != nil {
			return err
		}
	}
	return nil
}

// readArchive reads the file contents from tar file.
func readArchive(archive string) error {
	// Open the zip file specified by name and return a ReadCloser.
	rc, err := zip.OpenReader(archive)	
	if err != nil {
		return err
	}
	defer rc.Close()
	// Iterate through the files in the zip file to read the file contents.
	for _, file := range rc.File {
		frc, err := file.Open()
		if err != nil {
			return err
		}
		defer frc.Close()
		fmt.Fprintf(os.Stdout, "Contents of the file %s:\n", file.Name)
		// Write the contents into Stdout
		copied, err := io.Copy(os.Stdout, frc)
		if err != nil {
			return err
		}
		// Check the size of the file.
		if uint64(copied) != file.UncompressedSize64 {
			return fmt.Errorf("Length of the file contents doesn't match with the file %s", file.Name)
		}
		fmt.Println()
	}
	return nil
}

func main() {
	// Name of the zip file
	archive := "source.zip"
	// Files to be archived in zip format.
	files := []string{"main.go", "readme.txt"}
	// Archive files into zip format.
	err := archiveFiles(files, archive)
	if err != nil {
		log.Fatalf("Error while writing to zip file:%s\n", err)
	}
	// Read the file contents of tar file.
	err = readArchive(archive)
	if err != nil {
		log.Fatalf("Error while reading the zip file:%s\n", err)

	}
}


================================================
FILE: ch05/cmdflags/main.go
================================================
package main

import (
	"flag"
	"fmt"
)

func main() {

	fileName := flag.String("filename", "logfile", "File name for the log file")
	logLevel := flag.Int("loglevel", 0, "An integer value for Level (0-4)")
	isEnable := flag.Bool("enable", false, "A boolean value for enabling log options")
	var num int
	// Bind the flag to a variable.
	flag.IntVar(&num, "num", 25, "An integer value")

	// Parse parses flag definitions from the argument list.
	flag.Parse()
	// Get the values from pointers
	fmt.Println("filename:", *fileName)
	fmt.Println("loglevel:", *logLevel)
	fmt.Println("enable:", *isEnable)
	// Get the value from a variable
	fmt.Println("num:", num)
	// Args returns the non-flag command-line arguments.
	args := flag.Args()
	if len(args) > 0 {
		fmt.Println("The non-flag command-line arguments are:")
		// Print the arguments
		for _, v := range args {
			fmt.Println(v)
		}
	}

}


================================================
FILE: ch05/flag/main.go
================================================
package main

import (
	"flag"
	"fmt"
)

func main() {

	strPtr := flag.String("name", "Shiju", "a string")
	numbPtr := flag.Int("num", 25, "an int")
	boolPtr := flag.Bool("enable", false, "a bool")
	var num int
	flag.IntVar(&num, "num", 30, "an int")	
	// Parse parses flag definitions from the argument list.
	flag.Parse()
	// Get the values for pointers
	fmt.Println("name:", *strPtr)
	fmt.Println("num:", *numbPtr)
	fmt.Println("enable:", *boolPtr)
	// Get the value from a variable
	fmt.Println("num:", num)
	// Args returns the non-flag command-line arguments.
	fmt.Println("arguments:", flag.Args())
}


================================================
FILE: ch05/json/main.go
================================================
package main

import (
	"encoding/json"
	"fmt"
)

// Employee struct
type Employee struct {
	ID                            int
	FirstName, LastName, JobTitle string
}

func main() {
	emp := Employee{
		ID:        100,
		FirstName: "Shiju",
		LastName:  "Varghese",
		JobTitle:  "Architect",
	}
	// Encoding to JSON
	data, err := json.Marshal(emp)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	jsonStr := string(data)
	fmt.Println("The JSON data is:")
	fmt.Println(jsonStr)

	b := []byte(`{"ID":101,"FirstName":"Irene","LastName":"Rose","JobTitle":"Developer"}`)
	var emp1 Employee
	// Decoding JSON data to a value of struct type
	err = json.Unmarshal(b, &emp1)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println("The Employee value is:")
	fmt.Printf("ID:%d, Name:%s %s, JobTitle:%s", emp1.ID, emp1.FirstName, emp1.LastName, emp1.JobTitle)
}


================================================
FILE: ch05/jsontag/main.go
================================================
package main

import (
	"encoding/json"
	"fmt"
)

// Employee struct with struct tags
type Employee struct {
	ID        int    `json:"id,omitempty"`
	FirstName string `json:"firstname"`
	LastName  string `json:"lastname"`
	JobTitle  string `json:"job"`
}

func main() {
	emp := Employee{
		FirstName: "Shiju",
		LastName:  "Varghese",
		JobTitle:  "Architect",
	}
	// Encoding to JSON
	data, err := json.Marshal(emp)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	jsonStr := string(data)
	fmt.Println("The JSON data is:")
	fmt.Println(jsonStr)

	b := []byte(`{"id":101,"firstname":"Irene","lastname":"Rose","job":"Developer"}`)
	var emp1 Employee
	// Decoding JSON to a struct type
	err = json.Unmarshal(b, &emp1)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println("The Employee value is:")
	fmt.Printf("ID:%d, Name:%s %s, JobTitle:%s", emp1.ID, emp1.FirstName, emp1.LastName, emp1.JobTitle)
}


================================================
FILE: ch05/log/logger.go
================================================
package main

import (
	"io"
	"io/ioutil"
	"log"
	"os"
)

const (
	// UNSPECIFIED logs nothing
	UNSPECIFIED Level = iota // 0 :
	// TRACE logs everything
	TRACE // 1
	// INFO logs Info, Warnings and Errors
	INFO // 2
	// WARNING logs Warning and Errors
	WARNING // 3
	// ERROR just logs Errors
	ERROR // 4
)

// Level holds the log level.
type Level int

// Package level variables, which are pointer to log.Logger.
var (
	Trace   *log.Logger
	Info    *log.Logger
	Warning *log.Logger
	Error   *log.Logger
)

// initLog initializes log.Logger objects
func initLog(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warningHandle io.Writer,
	errorHandle io.Writer,
	isFlag bool) {

	// Flags for defines the logging properties, to log.New
	flag := 0
	if isFlag {
		flag = log.Ldate | log.Ltime | log.Lshortfile
	}

	// Create log.Logger objects.
	Trace = log.New(traceHandle, "TRACE: ", flag)
	Info = log.New(infoHandle, "INFO: ", flag)
	Warning = log.New(warningHandle, "WARNING: ", flag)
	Error = log.New(errorHandle, "ERROR: ", flag)

}

// SetLogLevel sets the logging level preference
func SetLogLevel(level Level) {

	// Creates os.*File, which has implemented io.Writer intreface
	f, err := os.OpenFile("logs.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalf("Error opening log file: %s", err.Error())
	}

	// Calls function initLog by specifying log level preference.
	switch level {
	case TRACE:
		initLog(f, f, f, f, true)
		return

	case INFO:
		initLog(ioutil.Discard, f, f, f, true)
		return

	case WARNING:
		initLog(ioutil.Discard, ioutil.Discard, f, f, true)
		return
	case ERROR:
		initLog(ioutil.Discard, ioutil.Discard, ioutil.Discard, f, true)
		return

	default:
		initLog(ioutil.Discard, ioutil.Discard, ioutil.Discard, ioutil.Discard, false)
		f.Close()
		return

	}
}


================================================
FILE: ch05/log/main.go
================================================
package main

import (
	"errors"
	"flag"
)

func main() {
	// Parse log level from command line
	logLevel := flag.Int("loglevel", 0, "an integer value (0-4)")
	flag.Parse()
	// Calling the SetLogLevel with the command-line argument
	SetLogLevel(Level(*logLevel))
	Trace.Println("Main started")
	loop()
	err := errors.New("Sample Error")
	Error.Println(err.Error())
	Trace.Println("Main completed")
}

// A simple function for the logging demo
func loop() {
	Trace.Println("Loop started")
	for i := 0; i < 10; i++ {
		Info.Println("Counter value is:", i)
	}
	Warning.Println("The counter variable is not being used")
	Trace.Println("Loop completed")
}


================================================
FILE: ch05/simplelog/main.go
================================================
package main

import (
	"errors"
	"io"
	"io/ioutil"
	"log"
	"os"
)

// Package level variables, which are pointer to log.Logger.
var (
	Trace   *log.Logger
	Info    *log.Logger
	Warning *log.Logger
	Error   *log.Logger
)

// initLog initializes log.Logger objects
func initLog(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warningHandle io.Writer,
	errorHandle io.Writer) {

	// Flags for defines the logging properties, to log.New
	flag := log.Ldate | log.Ltime | log.Lshortfile

	// Create log.Logger objects
	Trace = log.New(traceHandle, "TRACE: ", flag)
	Info = log.New(infoHandle, "INFO: ", flag)
	Warning = log.New(warningHandle, "WARNING: ", flag)
	Error = log.New(errorHandle, "ERROR: ", flag)

}

func main() {
	initLog(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)
	Trace.Println("Main started")
	loop()
	err := errors.New("Sample Error")
	Error.Println(err.Error())
	Trace.Println("Main completed")
}
func loop() {
	Trace.Println("Loop started")
	for i := 0; i < 10; i++ {
		Info.Println("Counter value is:", i)
	}
	Warning.Println("The counter variable is not being used")
	Trace.Println("Loop completed")
}


================================================
FILE: ch06/influx/main.go
================================================
// Example demo for working with InfluxDB
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"time"

	client "github.com/influxdata/influxdb/client/v2"
)

const (
	// DB provides the database name of the InfluxDB
	DB       = "metricsdb"
	username = "opsadmin"
	password = "pass123"
)

func main() {
	// Create client
	c := influxDBClient()
	// Write operations
	// Create metrics data for measurement "cpu"
	createMetrics(c)
	// Read operations
	// Read with limit of 10
	readWithLimit(c, 10)
	// Read mean value of "cpu_usage" for a region
	meanCPUUsage(c, "us-west")
	// Read count of records for a region
	countRegion(c, "us-west")

}

// influxDBClient returns InfluxDB Client
func influxDBClient() client.Client {
	c, err := client.NewHTTPClient(client.HTTPConfig{
		Addr:     "http://localhost:8086",
		Username: username,
		Password: password,
	})
	if err != nil {
		log.Fatalln("Error: ", err)
	}
	return c
}

// createMetrics write batch points to create the metrics data
func createMetrics(clnt client.Client) {
	batchCount := 100
	rand.Seed(42)

	// Create BatchPoints by giving config for InfluxDB
	bp, _ := client.NewBatchPoints(client.BatchPointsConfig{
		Database:  DB,
		Precision: "s",
	})
	// Batch update to adds Points
	for i := 0; i < batchCount; i++ {
		regions := []string{"us-west", "us-central", "us-north", "us-east"}
		// tagset – “host” and “region”
		tags := map[string]string{
			"host":   fmt.Sprintf("192.168.%d.%d", rand.Intn(100), rand.Intn(100)),
			"region": regions[rand.Intn(len(regions))],
		}

		value := rand.Float64() * 100.0
		// field - "cpu_usage"
		fields := map[string]interface{}{
			"cpu_usage": value,
		}

		pt, err := client.NewPoint("cpu", tags, fields, time.Now())

		if err != nil {
			log.Fatalln("Error: ", err)
		}
		// Add a Point
		bp.AddPoint(pt)

	}
	// Writes the batch update to add points to measurement "cpu"
	err := clnt.Write(bp)
	if err != nil {
		log.Fatalln("Error: ", err)
	}
}

// queryDB query the database
func queryDB(clnt client.Client, command string) (res []client.Result, err error) {
	// Create the query
	q := client.Query{
		Command:  command,
		Database: DB,
	}
	// Query the Database
	if response, err := clnt.Query(q); err == nil {
		if response.Error() != nil {
			return res, response.Error()
		}
		res = response.Results
	} else {
		return res, err
	}
	return res, nil
}

// readWithLimit reads records with a given limit
func readWithLimit(clnt client.Client, limit int) {
	q := fmt.Sprintf("SELECT * FROM %s LIMIT %d", "cpu", limit)
	res, err := queryDB(clnt, q)
	if err != nil {
		log.Fatalln("Error: ", err)
	}

	for i, row := range res[0].Series[0].Values {
		t, err := time.Parse(time.RFC3339, row[0].(string))
		if err != nil {
			log.Fatalln("Error: ", err)
		}
		val, err := row[1].(json.Number).Float64()
		fmt.Printf("[%2d] %s: %f\n", i, t.Format(time.Stamp), val)
	}
}

// meanCPUUsage reads the mean value of cpu_usage
func meanCPUUsage(clnt client.Client, region string) {
	q := fmt.Sprintf("select mean(%s) from %s where region = '%s'", "cpu_usage", "cpu", region)
	res, err := queryDB(clnt, q)
	if err != nil {
		log.Fatalln("Error: ", err)
	}
	value, err := res[0].Series[0].Values[0][1].(json.Number).Float64()
	if err != nil {
		log.Fatalln("Error: ", err)
	}

	fmt.Printf("Mean value of cpu_usage for region '%s':%f\n", region, value)
}

// countRegion reads the count of records for a given region
func countRegion(clnt client.Client, region string) {
	q := fmt.Sprintf("SELECT count(%s) FROM %s where region = '%s'", "cpu_usage", "cpu", region)
	res, err := queryDB(clnt, q)
	if err != nil {
		log.Fatalln("Error: ", err)
	}
	count := res[0].Series[0].Values[0][1]
	fmt.Printf("Found a total of %v records for region '%s'\n", count, region)
}


================================================
FILE: ch06/mongo/bookmark_store.go
================================================
package main

import (
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// Bookmark type reperesents the metadata of a bookmark.
type Bookmark struct {
	ID                          bson.ObjectId `bson:"_id,omitempty"`
	Name, Description, Location string
	Priority                    int // Priority (1 -5)
	CreatedOn                   time.Time
	Tags                        []string
}

// BookmarkStore provides CRUD operations against the collection "bookmarks".
type BookmarkStore struct {
	C *mgo.Collection
}

// Create inserts the value of struct Bookmark into collection.
func (store BookmarkStore) Create(b *Bookmark) error {
	// Assign a new bson.ObjectId
	b.ID = bson.NewObjectId()
	err := store.C.Insert(b)
	return err
}

//Update modifies an existing value of a collection.
func (store BookmarkStore) Update(b Bookmark) error {
	// partial update on MogoDB
	err := store.C.Update(bson.M{"_id": b.ID},
		bson.M{"$set": bson.M{
			"name":        b.Name,
			"description": b.Description,
			"location":    b.Location,
			"priority":    b.Priority,
			"tags":        b.Tags,
		}})
	return err
}

// Delete removes an existing value from the collection.
func (store BookmarkStore) Delete(id string) error {
	err := store.C.Remove(bson.M{"_id": bson.ObjectIdHex(id)})
	return err
}

// GetAll returns all documents from the collection.
func (store BookmarkStore) GetAll() []Bookmark {
	var b []Bookmark
	iter := store.C.Find(nil).Sort("priority", "-createdon").Iter()
	result := Bookmark{}
	for iter.Next(&result) {
		b = append(b, result)
	}
	return b
}

// GetByID returns single document from the collection.
func (store BookmarkStore) GetByID(id string) (Bookmark, error) {
	var b Bookmark
	err := store.C.FindId(bson.ObjectIdHex(id)).One(&b)
	return b, err
}

// GetByTag returns all documents from the collection filtering by tags.
func (store BookmarkStore) GetByTag(tags []string) []Bookmark {
	var b []Bookmark
	iter := store.C.Find(bson.M{"tags": bson.M{"$in": tags}}).Sort("priority", "-createdon").Iter()
	result := Bookmark{}
	for iter.Next(&result) {
		b = append(b, result)
	}
	return b
}


================================================
FILE: ch06/mongo/main.go
================================================
package main

import (
	"fmt"
	"log"
	"time"

	"gopkg.in/mgo.v2"
)

var store BookmarkStore
var id string

// init will invoke before the function main.
func init() {
	session, err := mgo.DialWithInfo(&mgo.DialInfo{
		Addrs:   []string{"127.0.0.1"},
		Timeout: 60 * time.Second,
	})
	if err != nil {
		log.Fatalf("[MongoDB Session]: %s\n", err)
	}
	collection := session.DB("bookmarkdb").C("bookmarks")
	collection.RemoveAll(nil)
	store = BookmarkStore{
		C: collection,
	}
}

// Create and update documents.
func createUpdate() {
	bookmark := Bookmark{
		Name:        "mgo",
		Description: "Go driver for MongoDB",
		Location:    "https://github.com/go-mgo/mgo",
		Priority:    2,
		CreatedOn:   time.Now(),
		Tags:        []string{"go", "nosql", "mongodb"},
	}
	// Insert a new document.
	if err := store.Create(&bookmark); err != nil {
		log.Fatalf("[Create]: %s\n", err)
	}
	id = bookmark.ID.Hex()
	fmt.Printf("New bookmark has been inserted with ID: %s\n", id)
	// Update an existing document.
	bookmark.Priority = 1
	if err := store.Update(bookmark); err != nil {
		log.Fatalf("[Update]: %s\n", err)
	}
	fmt.Println("The value after update:")
	// Retrieve the updated document.
	getByID(id)

	bookmark = Bookmark{
		Name:        "gorethink",
		Description: "Go driver for RethinkDB",
		Location:    "https://github.com/dancannon/gorethink",
		Priority:    3,
		CreatedOn:   time.Now(),
		Tags:        []string{"go", "nosql", "rethinkdb"},
	}
	// Insert a new document.
	if err := store.Create(&bookmark); err != nil {
		log.Fatalf("[Create]: %s\n", err)
	}
	id = bookmark.ID.Hex()
	fmt.Printf("New bookmark has been inserted with ID: %s\n", id)

}

// Get a document by given id.
func getByID(id string) {
	bookmark, err := store.GetByID(id)
	if err != nil {
		log.Fatalf("[GetByID]: %s\n", err)
	}
	fmt.Printf("Name:%s, Description:%s, Priority:%d\n",
		bookmark.Name, bookmark.Description, bookmark.Priority)
}

// Get all documents from the collection.
func getAll() {
	// Layout for formatting dates.
	layout := "2006-01-02 15:04:05"
	// Retrieve all documents.
	bookmarks := store.GetAll()
	fmt.Println("Read all documents")
	for _, v := range bookmarks {
		fmt.Printf("Name:%s, Description:%s, Priority:%d, CreatedOn:%s\n",
			v.Name, v.Description, v.Priority, v.CreatedOn.Format(layout))
	}
}

// Get documents by tags.
func getByTags() {
	layout := "2006-01-02 15:04:05"
	fmt.Println("Query with Tags - 'go, nosql'")
	bookmarks := store.GetByTag([]string{"go", "nosql"})
	for _, v := range bookmarks {
		fmt.Printf("Name:%s, Description:%s, Priority:%d, CreatedOn:%s\n",
			v.Name, v.Description, v.Priority, v.CreatedOn.Format(layout))
	}
	fmt.Println("Query with Tags - 'mongodb'")
	bookmarks = store.GetByTag([]string{"mongodb"})
	for _, v := range bookmarks {
		fmt.Printf("Name:%s, Description:%s, Priority:%d, CreatedOn:%s\n",
			v.Name, v.Description, v.Priority, v.CreatedOn.Format(layout))
	}
}

// Delete an existing document from the collection.
func delete() {
	if err := store.Delete(id); err != nil {
		log.Fatalf("[Delete]: %s\n", err)
	}
	bookmarks := store.GetAll()
	fmt.Printf("Number of documents in the collection after delete:%d\n", len(bookmarks))
}

// main - entry point of the program.
func main() {
	createUpdate()
	getAll()
	getByTags()
	delete()
}


================================================
FILE: ch06/postgres/main.go
================================================
package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/lib/pq"
)

// Product struct provides the data model for productstore
type Product struct {
	ID          int
	Title       string
	Description string
	Price       float32
}

var db *sql.DB

func init() {
	var err error
	db, err = sql.Open("postgres", "postgres://user:pass@localhost/productstore")
	if err != nil {
		log.Fatal(err)
	}
}
func main() {
	product := Product{
		Title:       "Amazon Echo",
		Description: "Amazon Echo - Black",
		Price:       179.99,
	}
	// Insert a product
	createProduct(product)
	// Read all product records
	getProducts()
	// Read a product by given id
	getProductByID(1)
}

// createProduct inserts product values into product table
func createProduct(prd Product) {
	result, err := db.Exec("INSERT INTO products(title, description, price) VALUES($1, $2, $3)", prd.Title, prd.Description, prd.Price)
	if err != nil {
		log.Fatal(err)
	}

	lastInsertID, err := result.LastInsertId()
	rowsAffected, err := result.RowsAffected()
	fmt.Printf("Product with id=%d created successfully (%d row affected)\n", lastInsertID, rowsAffected)
}

// getProducts reads all records from the product table
func getProducts() {
	rows, err := db.Query("SELECT * FROM products")
	if err != nil {
		if err == sql.ErrNoRows {
			fmt.Println("No Records Found")
			return
		}
		log.Fatal(err)
	}
	defer rows.Close()

	var products []*Product
	for rows.Next() {
		prd := &Product{}
		err := rows.Scan(&prd.Title, &prd.Description, &prd.Price)
		if err != nil {
			log.Fatal(err)
		}
		products = append(products, prd)
	}
	if err = rows.Err(); err != nil {
		log.Fatal(err)
	}

	for _, pr := range products {
		fmt.Printf("%s, %s, $%.2f\n", pr.Title, pr.Description, pr.Price)
	}
}

func getProductByID(id int) {
	var product string
	err := db.QueryRow("SELECT title FROM products WHERE id=$1", id).Scan(&product)
	switch {
	case err == sql.ErrNoRows:
		log.Printf("No product with that ID.")
	case err != nil:
		log.Fatal(err)
	default:
		fmt.Printf("Product is %s\n", product)
	}
}


================================================
FILE: ch06/rethink/bookmark_store.go
================================================
package main

import (
	"time"

	r "github.com/dancannon/gorethink"
)

// Bookmark type reperesents the metadata of a bookmark.
type Bookmark struct {
	ID                          string `gorethink:"id,omitempty" json:"id"`
	Name, Description, Location string
	Priority                    int // Priority (1 -5)
	CreatedOn                   time.Time
	Tags                        []string
}

// BookmarkStore provides CRUD operations against the Table "bookmarks".
type BookmarkStore struct {
	Session *r.Session
}

// Create inserts the value of struct Bookmark into Table.
func (store BookmarkStore) Create(b *Bookmark) error {

	resp, err := r.Table("bookmarks").Insert(b).RunWrite(store.Session)
	if err == nil {
		b.ID = resp.GeneratedKeys[0]
	}

	return err
}

// Update modifies an existing value of a Table.
func (store BookmarkStore) Update(b Bookmark) error {

	var data = map[string]interface{}{
		"description": b.Description,
		"location":    b.Location,
		"priority":    b.Priority,
		"tags":        b.Tags,
	}
	// partial update on RethinkDB
	_, err := r.Table("bookmarks").Get(b.ID).Update(data).RunWrite(store.Session)
	return err
}

// Delete removes an existing value from the Table.
func (store BookmarkStore) Delete(id string) error {
	_, err := r.Table("bookmarks").Get(id).Delete().RunWrite(store.Session)
	return err
}

// GetAll returns all documents from the Table.
func (store BookmarkStore) GetAll() ([]Bookmark, error) {
	bookmarks := []Bookmark{}

	res, err := r.Table("bookmarks").OrderBy("priority", r.Desc("createdon")).Run(store.Session)
	err = res.All(&bookmarks)
	return bookmarks, err
}

// GetByID returns single document from the Table.
func (store BookmarkStore) GetByID(id string) (Bookmark, error) {
	var b Bookmark
	res, err := r.Table("bookmarks").Get(id).Run(store.Session)
	res.One(&b)
	return b, err
}

// // GetByTag returns all documents from the collection filtering by tags.
// func (store BookmarkStore) GetByTag(tags []string) ([]Bookmark, error) {
// 	bookmarks := []Bookmark{}
// 	res, err := r.Table("bookmarks").Filter(func(row r.Term) r.Term {
// 		return r.Expr(tags).Contains(row.Field("tags"))
// 	}).Run(store.Session)
// 	err = res.All(&bookmarks)
// 	return bookmarks, err
// }


================================================
FILE: ch06/rethink/main.go
================================================
package main

import (
	"fmt"
	"log"
	"time"

	r "github.com/dancannon/gorethink"
)

var store BookmarkStore
var id string

// initDB creates new database and
func initDB(session *r.Session) {
	var err error
	// Create Database
	_, err = r.DBCreate("bookmarkdb").RunWrite(session)
	if err != nil {
		log.Fatalf("[initDB]: %s\n", err)
	}
	// Create Table
	_, err = r.DB("bookmarkdb").TableCreate("bookmarks").RunWrite(session)
	if err != nil {
		log.Fatalf("[initDB]: %s\n", err)
	}
}

// changeFeeds subscribes real-time updates on table bookmarks.
func changeFeeds(session *r.Session) {
	bookmarks, err := r.Table("bookmarks").Changes().Field("new_val").Run(session)
	if err != nil {
		log.Fatalf("[changeFeeds]: %s\n", err)
	}
	// Luanch a goroutine to print real-time updates.
	go func() {
		var bookmark Bookmark
		for bookmarks.Next(&bookmark) {
			if bookmark.ID == "" { // for delete, new_val will be null.
				fmt.Println("Real-time update: Document has been deleted")
			} else {
				fmt.Printf("Real-time update: Name:%s, Description:%s, Priority:%d\n",
					bookmark.Name, bookmark.Description, bookmark.Priority)
			}
		}
	}()
}

// init will invoke before the function main.
func init() {
	session, err := r.Connect(r.ConnectOpts{
		Address:  "localhost:28015",
		Database: "bookmarkdb",
		MaxIdle:  10,
		MaxOpen:  10,
	})

	if err != nil {
		log.Fatalf("[RethinkDB Session]: %s\n", err)
	}
	r.Table("bookmarks").Delete().Run(session)
	// Create Database and Table.
	//initDB(session)
	store = BookmarkStore{
		Session: session,
	}
	// Subscribe real-time changes
	changeFeeds(session)
}

// Create and update documents.
func createUpdate() {
	bookmark := Bookmark{
		Name:        "mgo",
		Description: "Go driver for MongoDB",
		Location:    "https://github.com/go-mgo/mgo",
		Priority:    1,
		CreatedOn:   time.Now(),
		Tags:        []string{"go", "nosql", "mongodb"},
	}
	// Insert a new document.
	if err := store.Create(&bookmark); err != nil {
		log.Fatalf("[Create]: %s\n", err)
	}
	id = bookmark.ID
	fmt.Printf("New bookmark has been inserted with ID: %s\n", id)
	// Retrieve the updated document.
	bookmark.Priority = 2
	if err := store.Update(bookmark); err != nil {
		log.Fatalf("[Update]: %s\n", err)
	}
	fmt.Println("The value after update:")
	// Retrieve an existing document by id.
	getByID(id)
	bookmark = Bookmark{
		Name:        "gorethink",
		Description: "Go driver for RethinkDB",
		Location:    "https://github.com/dancannon/gorethink",
		Priority:    1,
		CreatedOn:   time.Now(),
		Tags:        []string{"go", "nosql", "rethinkdb"},
	}
	// Insert a new document.
	if err := store.Create(&bookmark); err != nil {
		log.Fatalf("[Create]: %s\n", err)
	}
	id = bookmark.ID
	fmt.Printf("New bookmark has been inserted with ID: %s\n", id)

}

// Get a document by given id.
func getByID(id string) {
	bookmark, err := store.GetByID(id)
	if err != nil {
		log.Fatalf("[GetByID]: %s\n", err)
	}
	fmt.Printf("Name:%s, Description:%s, Priority:%d\n", bookmark.Name, bookmark.Description, bookmark.Priority)
}

// Get all documents from bookmarks table.
func getAll() {
	// Layout for formatting dates.
	layout := "2006-01-02 15:04:05"
	// Retrieve all documents.
	bookmarks, err := store.GetAll()
	if err != nil {
		log.Fatalf("[GetAll]: %s\n", err)
	}
	fmt.Println("Read all documents")
	for _, v := range bookmarks {
		fmt.Printf("Name:%s, Description:%s, Priority:%d, CreatedOn:%s\n", v.Name, v.Description, v.Priority, v.CreatedOn.Format(layout))
	}

}

// Delete an existing document from bookmarks table.
func delete() {
	if err := store.Delete(id); err != nil {
		log.Fatalf("[Delete]: %s\n", err)
	}
	bookmarks, err := store.GetAll()
	if err != nil {
		log.Fatalf("[GetAll]: %s\n", err)
	}
	fmt.Printf("Number of documents in the table after delete:%d\n", len(bookmarks))
}

// main - entry point of the program
func main() {
	createUpdate()
	getAll()
	delete()
}


================================================
FILE: ch07/bookmarkapi/common/auth.go
================================================
package common

import (
	"context"
	"crypto/rsa"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
	"github.com/dgrijalva/jwt-go/request"
)

// AppClaims provides custom claim for JWT
type AppClaims struct {
	UserName string `json:"username"`
	Role     string `json:"role"`
	jwt.StandardClaims
}

// using asymmetric crypto/RSA keys
// location of private/public key files
const (
	// openssl genrsa -out app.rsa 1024
	privKeyPath = "keys/app.rsa"
	// openssl rsa -in app.rsa -pubout > app.rsa.pub
	pubKeyPath = "keys/app.rsa.pub"
)

// Private key for signing and public key for verification
var (
	//verifyKey, signKey []byte
	verifyKey *rsa.PublicKey
	signKey   *rsa.PrivateKey
)

// Read the key files before starting http handlers
func initKeys() {

	signBytes, err := ioutil.ReadFile(privKeyPath)
	if err != nil {
		log.Fatalf("[initKeys]: %s\n", err)
	}

	signKey, err = jwt.ParseRSAPrivateKeyFromPEM(signBytes)
	if err != nil {
		log.Fatalf("[initKeys]: %s\n", err)
	}

	verifyBytes, err := ioutil.ReadFile(pubKeyPath)
	if err != nil {
		log.Fatalf("[initKeys]: %s\n", err)
	}

	verifyKey, err = jwt.ParseRSAPublicKeyFromPEM(verifyBytes)
	if err != nil {
		log.Fatalf("[initKeys]: %s\n", err)
	}
}

// GenerateJWT generates a new JWT token for authenticated user.
func GenerateJWT(name, role string) (string, error) {
	// Create the Claims
	claims := AppClaims{
		UserName: name,
		Role:     role,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Add(time.Minute * 20).Unix(),
			Issuer:    "admin",
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
	ss, err := token.SignedString(signKey)
	if err != nil {
		return "", err
	}
	return ss, nil
}

// AuthorizeRequest Middleware validates JWT tokens from incoming HTTP requests.
func AuthorizeRequest(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Get token from request
		token, err := request.ParseFromRequestWithClaims(r, request.OAuth2Extractor, &AppClaims{}, func(token *jwt.Token) (interface{}, error) {
			// since we only use the one private key to sign the tokens,
			// we also only use its public counter part to verify
			return verifyKey, nil
		})

		if err != nil {
			switch err.(type) {

			case *jwt.ValidationError: // JWT validation error
				vErr := err.(*jwt.ValidationError)

				switch vErr.Errors {
				case jwt.ValidationErrorExpired: //JWT expired
					DisplayAppError(
						w,
						err,
						"Access Token is expired, get a new Token",
						401,
					)
					return

				default:
					DisplayAppError(w,
						err,
						"Error while parsing the Access Token!",
						500,
					)
					return
				}

			default:
				DisplayAppError(w,
					err,
					"Error while parsing Access Token!",
					500)
				return
			}

		}
		if token.Valid {
			// Create a Context by setting the user name
			ctx := context.WithValue(r.Context(), "user", token.Claims.(*AppClaims).UserName)
			// Calls the next handler by providing the Context
			next.ServeHTTP(w, r.WithContext(ctx))
		} else {
			DisplayAppError(
				w,
				err,
				"Invalid Access Token",
				401,
			)
		}
	})
}

// AuthorizeRequestWithNegroni is a Negroni Middleware that validates JWT tokens
func AuthorizeRequestWithNegroni(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {

	// Get token from request
	token, err := request.ParseFromRequestWithClaims(r, request.OAuth2Extractor, &AppClaims{}, func(token *jwt.Token) (interface{}, error) {
		// since we only use the one private key to sign the tokens,
		// we also only use its public counter part to verify
		return verifyKey, nil
	})

	if err != nil {
		switch err.(type) {

		case *jwt.ValidationError: // JWT validation error
			vErr := err.(*jwt.ValidationError)

			switch vErr.Errors {
			case jwt.ValidationErrorExpired: //JWT expired
				DisplayAppError(
					w,
					err,
					"Access Token is expired, get a new Token",
					401,
				)
				return

			default:
				DisplayAppError(w,
					err,
					"Error while parsing the Access Token!",
					500,
				)
				return
			}

		default:
			DisplayAppError(w,
				err,
				"Error while parsing Access Token!",
				500)
			return
		}

	}
	if token.Valid {
		ctx := context.WithValue(r.Context(), "user", token.Claims.(*AppClaims).UserName)
		next(w, r.WithContext(ctx))
	} else {
		DisplayAppError(
			w,
			err,
			"Invalid Access Token",
			401,
		)
	}
}

// TokenFromAuthHeader is a "TokenExtractor" that takes a given request and extracts
// the JWT token from the Authorization header.
func TokenFromAuthHeader(r *http.Request) (string, error) {
	// Look for an Authorization header
	if ah := r.Header.Get("Authorization"); ah != "" {
		// Should be a bearer token
		if len(ah) > 6 && strings.ToUpper(ah[0:6]) == "BEARER" {
			return ah[7:], nil
		}
	}
	return "", errors.New("No token in the HTTP request")
}


================================================
FILE: ch07/bookmarkapi/common/bootstrapper.go
================================================
package common

// StartUp bootstrapps the application
func StartUp() {
	// Initialize AppConfig variable
	initConfig()
	// Initialize private/public keys for JWT authentication
	initKeys()
	// Initialize Logger objects with Log Level
	setLogLevel(Level(AppConfig.LogLevel))
	// Start a MongoDB session
	createDBSession()
	// Add indexes into MongoDB
	addIndexes()
}


================================================
FILE: ch07/bookmarkapi/common/config.json
================================================
{
  "Server"      : "0.0.0.0:8080",
  "MongoDBHost" : "127.0.0.1",
  "MongoDBUser"	: "",
  "MongoDBPwd"	: "",
  "Database"    : "bookmarkdb",
  "LogLevel"    : 4
}


================================================
FILE: ch07/bookmarkapi/common/logger.go
================================================
package common

import (
	"io"
	"io/ioutil"
	"log"
	"os"
)

const (
	// UNSPECIFIED logs nothing
	UNSPECIFIED Level = iota // 0 :
	// TRACE logs everything
	TRACE // 1
	// INFO logs Info, Warnings and Errors
	INFO // 2
	// WARNING logs Warning and Errors
	WARNING // 3
	// ERROR just logs Errors
	ERROR // 4
)

// Level holds the log level.
type Level int

// Package level variables, which are pointer to log.Logger.
var (
	Trace   *log.Logger
	Info    *log.Logger
	Warning *log.Logger
	Error   *log.Logger
)

// initLog initializes log.Logger objects
func initLog(
	traceHandle io.Writer,
	infoHandle io.Writer,
	warningHandle io.Writer,
	errorHandle io.Writer,
	isFlag bool) {

	// Flags for defines the logging properties, to log.New
	flag := 0
	if isFlag {
		flag = log.Ldate | log.Ltime | log.Lshortfile
	}

	// Create log.Logger objects.
	Trace = log.New(traceHandle, "TRACE: ", flag)
	Info = log.New(infoHandle, "INFO: ", flag)
	Warning = log.New(warningHandle, "WARNING: ", flag)
	Error = log.New(errorHandle, "ERROR: ", flag)

}

// SetLogLevel sets the logging level preference
func setLogLevel(level Level) {

	// Creates os.*File, which has implemented io.Writer intreface
	f, err := os.OpenFile("logs.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalf("Error opening log file: %s", err.Error())
	}

	// Calls function initLog by specifying log level preference.
	switch level {
	case TRACE:
		initLog(f, f, f, f, true)
		return

	case INFO:
		initLog(ioutil.Discard, f, f, f, true)
		return

	case WARNING:
		initLog(ioutil.Discard, ioutil.Discard, f, f, true)
		return
	case ERROR:
		initLog(ioutil.Discard, ioutil.Discard, ioutil.Discard, f, true)
		return

	default:
		initLog(ioutil.Discard, ioutil.Discard, ioutil.Discard, ioutil.Discard, false)
		f.Close()
		return

	}
}


================================================
FILE: ch07/bookmarkapi/common/mongo_utils.go
================================================
package common

import (
	"log"
	"time"

	"gopkg.in/mgo.v2"
)

var session *mgo.Session

// GetSession returns a MongoDB Session
func getSession() *mgo.Session {
	if session == nil {
		var err error
		session, err = mgo.DialWithInfo(&mgo.DialInfo{
			Addrs:    []string{AppConfig.MongoDBHost},
			Username: AppConfig.DBUser,
			Password: AppConfig.DBPwd,
			Timeout:  60 * time.Second,
		})
		if err != nil {
			log.Fatalf("[GetSession]: %s\n", err)
		}
	}
	return session
}
func createDBSession() {
	var err error
	session, err = mgo.DialWithInfo(&mgo.DialInfo{
		Addrs:    []string{AppConfig.MongoDBHost},
		Username: AppConfig.DBUser,
		Password: AppConfig.DBPwd,
		Timeout:  60 * time.Second,
	})
	if err != nil {
		log.Fatalf("[createDbSession]: %s\n", err)
	}
}

// Add indexes into MongoDB
func addIndexes() {
	var err error
	userIndex := mgo.Index{
		Key:        []string{"email"},
		Unique:     true,
		Background: true,
		Sparse:     true,
	}
	// Add indexes into MongoDB
	session := getSession().Copy()
	defer session.Close()
	userCol := session.DB(AppConfig.Database).C("users")

	err = userCol.EnsureIndex(userIndex)
	if err != nil {
		log.Fatalf("[addIndexes]: %s\n", err)
	}
}

// DataStore for MongoDB
type DataStore struct {
	MongoSession *mgo.Session
}

// Close closes a mgo.Session value.
// Used to add defer statements for closing the copied session.
func (ds *DataStore) Close() {
	ds.MongoSession.Close()
}

// Collection returns mgo.collection for the given name
func (ds *DataStore) Collection(name string) *mgo.Collection {
	return ds.MongoSession.DB(AppConfig.Database).C(name)
}

// NewDataStore creates a new DataStore object to be used for each HTTP request.
func NewDataStore() *DataStore {
	session := getSession().Copy()
	dataStore := &DataStore{
		MongoSession: session,
	}
	return dataStore
}


================================================
FILE: ch07/bookmarkapi/common/utils.go
================================================
package common

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
)

type (
	appError struct {
		Error      string `json:"error"`
		Message    string `json:"message"`
		HTTPStatus int    `json:"status"`
	}
	errorResource struct {
		Data appError `json:"data"`
	}
	configuration struct {
		Server, MongoDBHost, DBUser, DBPwd, Database string
		LogLevel                                     int
	}
)

// DisplayAppError provides app specific error in JSON
func DisplayAppError(w http.ResponseWriter, handlerError error, message string, code int) {
	errObj := appError{
		Error:      handlerError.Error(),
		Message:    message,
		HTTPStatus: code,
	}
	//log.Printf("AppError]: %s\n", handlerError)
	Error.Printf("AppError]: %s\n", handlerError)
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(code)
	if j, err := json.Marshal(errorResource{Data: errObj}); err == nil {
		w.Write(j)
	}
}

// AppConfig holds the configuration values from config.json file
var AppConfig configuration

// Initialize AppConfig
func initConfig() {
	loadAppConfig()
}

// Reads config.json and decode into AppConfig
func loadAppConfig() {
	file, err := os.Open("common/config.json")
	defer file.Close()
	if err != nil {
		log.Fatalf("[loadConfig]: %s\n", err)
	}
	decoder := json.NewDecoder(file)
	AppConfig = configuration{}
	err = decoder.Decode(&AppConfig)
	if err != nil {
		log.Fatalf("[loadAppConfig]: %s\n", err)
	}
}


================================================
FILE: ch07/bookmarkapi/controllers/bookmark_controller.go
================================================
package controllers

import (
	"encoding/json"
	"net/http"

	"github.com/gorilla/mux"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/common"
	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/store"
)

// CreateBookmark insert a new Bookmark.
// Handler for HTTP Post - "/bookmarks
func CreateBookmark(w http.ResponseWriter, r *http.Request) {
	var dataResource BookmarkResource
	// Decode the incoming Bookmark json
	err := json.NewDecoder(r.Body).Decode(&dataResource)
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"Invalid Bookmark data",
			500,
		)
		return
	}
	bookmark := &dataResource.Data
	// Creates a new DatStore value to working with MongoDB store.
	dataStore := common.NewDataStore()
	// Add to the mgo.Session.Close()
	defer dataStore.Close()
	// Get the mgo.Collection for "bookmarks"
	col := dataStore.Collection("bookmarks")
	// Creates an instance of BookmarkStore
	bookmarkStore := store.BookmarkStore{C: col}
	// Takes user name from Context
	user := r.Context().Value("user")
	if user != nil {
		bookmark.CreatedBy = user.(string)
	}
	// Insert a bookmark document
	err = bookmarkStore.Create(bookmark)
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"Invalid Bookmark data",
			500,
		)
		return
	}
	j, err := json.Marshal(BookmarkResource{Data: *bookmark})
	// If error is occured,
	// Send JSON response using helper function common.DisplayAppError
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"An unexpected error has occurred",
			500,
		)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	// Write the JSON data to the ResponseWriter
	w.Write(j)

}

// GetBookmarks returns all Bookmark documents
// Handler for HTTP Get - "/Bookmarks"
func GetBookmarks(w http.ResponseWriter, r *http.Request) {
	dataStore := common.NewDataStore()
	defer dataStore.Close()
	col := dataStore.Collection("bookmarks")
	bookmarkStore := store.BookmarkStore{C: col}
	bookmarks := bookmarkStore.GetAll()
	j, err := json.Marshal(BookmarksResource{Data: bookmarks})
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"An unexpected error has occurred",
			500,
		)
		return
	}
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

// GetBookmarkByID returns a single bookmark document by id
// Handler for HTTP Get - "/Bookmarks/{id}"
func GetBookmarkByID(w http.ResponseWriter, r *http.Request) {
	// Get id from the incoming url
	vars := mux.Vars(r)
	id := vars["id"]

	dataStore := common.NewDataStore()
	defer dataStore.Close()
	col := dataStore.Collection("bookmarks")
	bookmarkStore := store.BookmarkStore{C: col}

	bookmark, err := bookmarkStore.GetByID(id)
	if err != nil {
		if err == mgo.ErrNotFound {
			w.WriteHeader(http.StatusNoContent)

		} else {
			common.DisplayAppError(
				w,
				err,
				"An unexpected error has occurred",
				500,
			)

		}
		return
	}
	j, err := json.Marshal(bookmark)
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"An unexpected error has occurred",
			500,
		)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(j)
}

// GetBookmarksByUser returns all Bookmarks created by a User
// Handler for HTTP Get - "/Bookmarks/users/{id}"
func GetBookmarksByUser(w http.ResponseWriter, r *http.Request) {
	// Get id from the incoming url
	vars := mux.Vars(r)
	user := vars["id"]
	dataStore := common.NewDataStore()
	defer dataStore.Close()
	col := dataStore.Collection("bookmarks")
	bookmarkStore := store.BookmarkStore{C: col}
	bookmarks := bookmarkStore.GetByUser(user)
	j, err := json.Marshal(BookmarksResource{Data: bookmarks})
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"An unexpected error has occurred",
			500,
		)
		return
	}
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")
	w.Write(j)
}

// UpdateBookmark update an existing Bookmark document
// Handler for HTTP Put - "/Bookmarks/{id}"
func UpdateBookmark(w http.ResponseWriter, r *http.Request) {
	// Get id from the incoming url
	vars := mux.Vars(r)
	id := bson.ObjectIdHex(vars["id"])
	var dataResource BookmarkResource
	// Decode the incoming Bookmark json
	err := json.NewDecoder(r.Body).Decode(&dataResource)
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"Invalid Bookmark data",
			500,
		)
		return
	}
	bookmark := dataResource.Data
	bookmark.ID = id
	dataStore := common.NewDataStore()
	defer dataStore.Close()
	col := dataStore.Collection("bookmarks")
	bookmarkStore := store.BookmarkStore{C: col}
	// Update an existing Bookmark document
	if err := bookmarkStore.Update(bookmark); err != nil {
		common.DisplayAppError(
			w,
			err,
			"An unexpected error has occurred",
			500,
		)
		return
	}
	w.WriteHeader(http.StatusNoContent)

}

// DeleteBookmark deletes an existing Bookmark document
// Handler for HTTP Delete - "/Bookmarks/{id}"
func DeleteBookmark(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["id"]
	dataStore := common.NewDataStore()
	defer dataStore.Close()
	col := dataStore.Collection("bookmarks")
	bookmarkStore := store.BookmarkStore{C: col}
	// Delete an existing Bookmark document
	err := bookmarkStore.Delete(id)
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"An unexpected error has occurred",
			500,
		)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}


================================================
FILE: ch07/bookmarkapi/controllers/resources.go
================================================
package controllers

import (
	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/model"
)

//Models for JSON resources
type (
	// UserResource For Post - /user/register
	UserResource struct {
		Data UserModel `json:"data"`
	}
	// AuthUserResource Response for authorized user Post - /user/login
	AuthUserResource struct {
		Data AuthUserModel `json:"data"`
	}
	// BookmarkResource For Post/Put - /bookmarks
	// For Get - /bookmarks/id
	BookmarkResource struct {
		Data model.Bookmark `json:"data"`
	}
	// BookmarksResource for Get - /bookmarks
	BookmarksResource struct {
		Data []model.Bookmark `json:"data"`
	}

	// UserModel reperesents a user
	UserModel struct {
		FirstName string `json:"firstname"`
		LastName  string `json:"lastname"`
		Email     string `json:"email"`
		Password  string `json:"password"`
	}
	// AuthUserModel for authorized user with access token
	AuthUserModel struct {
		User  model.User `json:"user"`
		Token string     `json:"token"`
	}
)


================================================
FILE: ch07/bookmarkapi/controllers/user_controller.go
================================================
package controllers

import (
	"encoding/json"
	"net/http"

	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/common"
	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/model"
	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/store"
)

// Register add a new User document
// Handler for HTTP Post - "/users/register"
func Register(w http.ResponseWriter, r *http.Request) {
	var dataResource UserResource
	// Decode the incoming User json
	err := json.NewDecoder(r.Body).Decode(&dataResource)
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"Invalid User data",
			500,
		)
		return
	}
	userModel := dataResource.Data
	dataStore := common.NewDataStore()
	defer dataStore.Close()
	col := dataStore.Collection("users")
	userStore := store.UserStore{C: col}
	user := model.User{
		FirstName: userModel.FirstName,
		LastName:  userModel.LastName,
		Email:     userModel.Email,
	}
	// Insert User document
	userStore.Create(user, userModel.Password)
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
}

// Login authenticates the HTTP request with username and apssword
// Handler for HTTP Post - "/users/login"
func Login(w http.ResponseWriter, r *http.Request) {
	var dataResource UserResource
	var token string
	// Decode the incoming Login json
	err := json.NewDecoder(r.Body).Decode(&dataResource)
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"Invalid Login data",
			500,
		)
		return
	}
	loginUser := dataResource.Data
	dataStore := common.NewDataStore()
	defer dataStore.Close()
	col := dataStore.Collection("users")
	userStore := store.UserStore{C: col}
	// Authenticate the login user
	user, err := userStore.Login(loginUser.Email, loginUser.Password)
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"Invalid login credentials",
			401,
		)
		return
	}
	// Generate JWT token
	token, err = common.GenerateJWT(user.Email, "member")
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"Eror while generating the access token",
			500,
		)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	// Clean-up the hashpassword to eliminate it from response JSON
	user.HashPassword = nil
	authUser := AuthUserModel{
		User:  user,
		Token: token,
	}
	j, err := json.Marshal(AuthUserResource{Data: authUser})
	if err != nil {
		common.DisplayAppError(
			w,
			err,
			"An unexpected error has occurred",
			500,
		)
		return
	}
	w.WriteHeader(http.StatusOK)
	w.Write(j)
}


================================================
FILE: ch07/bookmarkapi/keys/app.rsa
================================================
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDPSMNALgfEMEDbS3kCLiTlpx0S4tZH1jZLcGF5Pjhc9IuEIf7p
6obYT1W7urDPWM8JGO1mdx+GnJCnPcvFSsX8FjGwDqIp7afTdislYCJwQLXL7qPz
wvG7ZlrtXrC9+0xkDGNxB+5Cui++8gWGbfTpTZiCiP413esxVQ30btKk2QIDAQAB
AoGACfj1M9RDGWQ86pAB/WHc8pOMqYjySDh9GjoI5n1g1tAJGk1MZ1KaNDP06vg7
Y25hX42sdj6K7L4Bk5o8gHxtc/IsheSeUFbdqbFdiAzTxgHq2zi1ZRPaxtNuw1Wk
KPxcehMpXl/eKCY50+bkVUTvBtfPjRat0fSZnQ4X24zHcAECQQDtU1S/Lu/7vfKI
BR9P2VoCfJvGuwpMcoaXcJuH9oEbeGKnSd7cKVeZdtuapHFjAm/yPWveOYmjrg6a
CiPIgWoBAkEA35hIN/f6wzpLiKPB1TERO/YH1qrRKoM17Y7qcqh8pjmfgY/8we6m
aGrFPd2eUVEpo5XMhQVpsluHmG8ZbXvK2QJAUlfueKM9ixg91WoJkjf03hYEKrDt
Atdd0Z+1pzglVbWwbSDZXYROq6WsznwuB09qLh+XlLRcCFm1IUdRYRleAQJAWQI9
FZKxD5CgSwetfNnom28IlcswMvVCvYvcBsLNxDpCJgiUvPrs4bpHRKZ5hLODmOxk
GzwZZHgNVYA8phnWmQJAER8blPRwsHaEUdPLKWPffvlGPh8RJwpWtaneBOhkyylh
HbPOBvC2WGJ7uXYTiXPHwOeLyRtUYx2GaoKQImi3sw==
-----END RSA PRIVATE KEY-----


================================================
FILE: ch07/bookmarkapi/keys/app.rsa.pub
================================================
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPSMNALgfEMEDbS3kCLiTlpx0S
4tZH1jZLcGF5Pjhc9IuEIf7p6obYT1W7urDPWM8JGO1mdx+GnJCnPcvFSsX8FjGw
DqIp7afTdislYCJwQLXL7qPzwvG7ZlrtXrC9+0xkDGNxB+5Cui++8gWGbfTpTZiC
iP413esxVQ30btKk2QIDAQAB
-----END PUBLIC KEY-----


================================================
FILE: ch07/bookmarkapi/main.go
================================================
package main

import (
	"log"
	"net/http"

	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/common"
	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/routers"
)

// Entry point of the program
func main() {

	// Calls startup logic
	common.StartUp()
	// Get the mux router object
	router := routers.InitRoutes()
	// Create the Server
	server := &http.Server{
		Addr:    common.AppConfig.Server,
		Handler: router,
	}
	log.Println("Listening...")
	// Running the HTTP Server
	server.ListenAndServe()
}


================================================
FILE: ch07/bookmarkapi/model/models.go
================================================
package model

import (
	"time"

	"gopkg.in/mgo.v2/bson"
)

type (
	// User type represents the registered user.
	User struct {
		ID           bson.ObjectId `bson:"_id,omitempty" json:"id"`
		FirstName    string        `json:"firstname"`
		LastName     string        `json:"lastname"`
		Email        string        `json:"email"`
		HashPassword []byte        `json:"hashpassword,omitempty"`
	}
	// Bookmark type represents the metadata of a bookmark.
	Bookmark struct {
		ID          bson.ObjectId `bson:"_id,omitempty"`
		Name        string        `json:"name"`
		Description string        `json:"description"`
		Location    string        `json:"location"`
		Priority    int           `json:"priority"` // Priority (1 -5)
		CreatedBy   string        `json:"createdby"`
		CreatedOn   time.Time     `json:"createdon,omitempty"`
		Tags        []string      `json:"tags,omitempty"`
	}
)


================================================
FILE: ch07/bookmarkapi/routers/bookmark.go
================================================
package routers

import (
	"github.com/gorilla/mux"

	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/common"
	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/controllers"
)

// SetBookmarkRoutes registers routes for bookmark entity.
func SetBookmarkRoutes(router *mux.Router) *mux.Router {
	bookmarkRouter := mux.NewRouter()
	bookmarkRouter.HandleFunc("/bookmarks", controllers.CreateBookmark).Methods("POST")
	bookmarkRouter.HandleFunc("/bookmarks/{id}", controllers.UpdateBookmark).Methods("PUT")
	bookmarkRouter.HandleFunc("/bookmarks", controllers.GetBookmarks).Methods("GET")
	bookmarkRouter.HandleFunc("/bookmarks/{id}", controllers.GetBookmarkByID).Methods("GET")
	bookmarkRouter.HandleFunc("/bookmarks/users/{id}", controllers.GetBookmarksByUser).Methods("GET")
	bookmarkRouter.HandleFunc("/bookmarks/{id}", controllers.DeleteBookmark).Methods("DELETE")
	router.PathPrefix("/bookmarks").Handler(common.AuthorizeRequest(bookmarkRouter))
	return router
}


================================================
FILE: ch07/bookmarkapi/routers/routers.go
================================================
package routers

import (
	"github.com/gorilla/mux"
)

// InitRoutes registers all routes for the application.
func InitRoutes() *mux.Router {
	router := mux.NewRouter().StrictSlash(false)
	// Routes for the User entity
	router = SetUserRoutes(router)
	// Routes for the Bookmark entity
	router = SetBookmarkRoutes(router)
	return router
}


================================================
FILE: ch07/bookmarkapi/routers/user.go
================================================
package routers

import (
	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/controllers"

	"github.com/gorilla/mux"
)

// SetUserRoutes registers routes for user entity
func SetUserRoutes(router *mux.Router) *mux.Router {
	router.HandleFunc("/users", controllers.Register).Methods("POST")
	router.HandleFunc("/users/login", controllers.Login).Methods("POST")
	return router
}


================================================
FILE: ch07/bookmarkapi/store/bookmark_store.go
================================================
package store

import (
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/model"
)

// BookmarkStore provides CRUD operations against the collection "bookmarks".
type BookmarkStore struct {
	C *mgo.Collection
}

// Create inserts the value of struct Bookmark into collection.
func (store BookmarkStore) Create(b *model.Bookmark) error {
	// Assign a new bson.ObjectId
	b.ID = bson.NewObjectId()
	b.CreatedOn = time.Now()
	err := store.C.Insert(b)
	return err
}

// Update modifies an existing document of a collection.
func (store BookmarkStore) Update(b model.Bookmark) error {
	// partial update on MogoDB
	err := store.C.Update(bson.M{"_id": b.ID},
		bson.M{"$set": bson.M{
			"name":        b.Name,
			"description": b.Description,
			"location":    b.Location,
			"priority":    b.Priority,
			"tags":        b.Tags,
		}})
	return err
}

// Delete removes an existing document from the collection.
func (store BookmarkStore) Delete(id string) error {
	err := store.C.Remove(bson.M{"_id": bson.ObjectIdHex(id)})
	return err
}

// GetAll returns all documents from the collection.
func (store BookmarkStore) GetAll() []model.Bookmark {
	var b []model.Bookmark
	iter := store.C.Find(nil).Sort("priority", "-createdon").Iter()
	result := model.Bookmark{}
	for iter.Next(&result) {
		b = append(b, result)
	}
	return b
}

// GetByUser returns all documents from the collection.
func (store BookmarkStore) GetByUser(user string) []model.Bookmark {
	var b []model.Bookmark
	iter := store.C.Find(bson.M{"createdby": user}).Sort("priority", "-createdon").Iter()
	result := model.Bookmark{}
	for iter.Next(&result) {
		b = append(b, result)
	}
	return b
}

// GetByID returns a single document from the collection.
func (store BookmarkStore) GetByID(id string) (model.Bookmark, error) {
	var b model.Bookmark
	err := store.C.FindId(bson.ObjectIdHex(id)).One(&b)
	return b, err
}

// GetByTag returns all documents from the collection filtering by tags.
func (store BookmarkStore) GetByTag(tags []string) []model.Bookmark {
	var b []model.Bookmark
	iter := store.C.Find(bson.M{"tags": bson.M{"$in": tags}}).Sort("priority", "-createdon").Iter()
	result := model.Bookmark{}
	for iter.Next(&result) {
		b = append(b, result)
	}
	return b
}


================================================
FILE: ch07/bookmarkapi/store/user_store.go
================================================
package store

import (
	"golang.org/x/crypto/bcrypt"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"github.com/shijuvar/go-recipes/ch07/bookmarkapi/model"
)

// UserStore provides persistence logic for "users" collection.
type UserStore struct {
	C *mgo.Collection
}

// Create insert new User
func (store UserStore) Create(user model.User, password string) error {

	user.ID = bson.NewObjectId()
	hpass, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	user.HashPassword = hpass
	err = store.C.Insert(user)
	return err
}

// Login authenticates the User
func (store UserStore) Login(email, password string) (model.User, error) {
	var user model.User
	err := store.C.Find(bson.M{"email": email}).One(&user)
	if err != nil {
		return model.User{}, err
	}
	// Validate password
	err = bcrypt.CompareHashAndPassword(user.HashPassword, []byte(password))
	if err != nil {
		return model.User{}, err
	}
	return user, nil
}


================================================
FILE: ch07/customhandler/main.go
================================================
package main

import (
	"fmt"
	"log"
	"net/http"
)

type textHandler struct {
	responseText string
}

func (th *textHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, th.responseText)
}

type indexHandler struct {
}

func (ih *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set(
		"Content-Type",
		"text/html",
	)
	html :=
		`<doctype html>
        <html>
	<head>
		<title>Hello Gopher</title>
	</head>
	<body>
		<b>Hello Gopher!</b>
        <p>
          <a href="/welcome">Welcome</a> |  <a href="/message">Message</a>
        </p>
	</body>
</html>`
	fmt.Fprintf(w, html)

}

func main() {
	mux := http.NewServeMux()
	mux.Handle("/", &indexHandler{})

	thWelcome := &textHandler{"Welcome to Go Web Programming"}
	mux.Handle("/welcome", thWelcome)

	thMessage := &textHandler{"net/http package is used to build web apps"}
	mux.Handle("/message", thMessage)

	log.Println("Listening...")
	http.ListenAndServe(":8080", mux)
}


================================================
FILE: ch07/defaultservemux/main.go
================================================
package main

import (
	"fmt"
	"log"
	"net/http"
)

func index(w http.ResponseWriter, r *http.Request) {
	w.Header().Set(
		"Content-Type",
		"text/html",
	)
	html :=
		`<doctype html>
        <html>
	<head>
		<title>Hello Gopher</title>
	</head>
	<body>
		<b>Hello Gopher!</b>
        <p>
            <a href="/welcome">Welcome</a> |  <a href="/message">Message</a>
        </p>
	</body>
</html>`
	fmt.Fprintf(w, html)
}

func welcome(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to Go Web Programming")
}
func message(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "net/http package is used to build web apps")
}

func main() {
	http.HandleFunc("/", index)
	http.HandleFunc("/welcome", welcome)
	http.HandleFunc("/message", message)
	log.Println("Listening...")
	http.ListenAndServe(":8080", nil)
}


================================================
FILE: ch07/handlefunc/main.go
================================================
package main

import (
	"fmt"
	"log"
	"net/http"
)

func index(w http.ResponseWriter, r *http.Request) {
	w.Header().Set(
		"Content-Type",
		"text/html",
	)
	html :=
		`<doctype html>
        <html>
	<head>
		<title>Hello Gopher</title>
	</head>
	<body>
		<b>Hello Gopher!</b>
        <p>
            <a href="/welcome">Welcome</a> |  <a href="/message">Message</a>
        </p>
	</body>
</html>`
	fmt.Fprintf(w, html)
}

func welcome(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to Go Web Programming")
}
func message(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "net/http package is used to build web apps")
}

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", index)
	mux.HandleFunc("/welcome", welcome)
	mux.HandleFunc("/message", message)
	log.Println("Listening...")
	http.ListenAndServe(":8080", mux)
}


================================================
FILE: ch07/handlerfunc/main.go
================================================
package main

import (
	"fmt"
	"log"
	"net/http"
)

func textResponseHandler(resposeText string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, resposeText)
	})
}
func index(w http.ResponseWriter, r *http.Request) {
	w.Header().Set(
		"Content-Type",
		"text/html",
	)
	html :=
		`<doctype html>
        <html>
	<head>
		<title>Hello Gopher</title>
	</head>
	<body>
		<b>Hello Gopher!</b>
        <p>
            <a href="/welcome">Welcome</a> |  <a href="/message">Message</a>
        </p>
	</body>
</html>`
	fmt.Fprintf(w, html)
}

func welcome(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to Go Web Programming")
}
func message(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "net/http package is used to build web apps")
}

func main() {
	mux := http.NewServeMux()
	mux.Handle("/", http.HandlerFunc(index))
	mux.Handle("/welcome", http.HandlerFunc(welcome))
	mux.Handle("/message", http.HandlerFunc(message))
	//mux.Handle("/welcome", textResponseHandler("Welcome to Go Web Programming"))
	//mux.Handle("/message", textResponseHandler("net/http package is used to build web apps"))

	log.Println("Listening...")
	http.ListenAndServe(":8080", mux)
}


================================================
FILE: ch07/httpserver/main.go
================================================
package main

import (
	"fmt"
	"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello, world!")
}

func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}


================================================
FILE: ch07/middleware/main.go
================================================
package main

import (
	"fmt"
	"log"
	"net/http"
	"time"
)

// loggingHandler is an HTTP Middleware that logs HTTP requests.
func loggingHandler(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Middleware logic before executing given Handler
		start := time.Now()
		log.Printf("Started %s %s", r.Method, r.URL.Path)
		next.ServeHTTP(w, r)
		// Middleware logic after executing given Handler
		log.Printf("Completed %s in %v", r.URL.Path, time.Since(start))
	})
}

func index(w http.ResponseWriter, r *http.Request) {
	w.Header().Set(
		"Content-Type",
		"text/html",
	)
	html :=
		`<doctype html>
        <html>
	<head>
		<title>Hello Gopher</title>
	</head>
	<body>
		<b>Hello Gopher!</b>
        <p>
            <a href="/welcome">Welcome</a> |  <a href="/message">Message</a>
        </p>
	</body>
</html>`
	fmt.Fprintf(w, html)
}

func welcome(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to Go Web Programming")
}
func message(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "net/http package is used to build web apps")
}
func favicon(w http.ResponseWriter, r *http.Request) {
}

func main() {
	http.HandleFunc("/favicon.ico", favicon)
	http.Handle("/", loggingHandler(http.HandlerFunc(index)))
	http.Handle("/welcome", loggingHandler(http.HandlerFunc(welcome)))
	http.Handle("/message", loggingHandler(http.HandlerFunc(message)))
	log.Println("Listening...")
	http.ListenAndServe(":8080", nil)
}


================================================
FILE: ch07/server/main.go
================================================
package main

import (
	"fmt"
	"log"
	"net/http"
	"time"
)

func index(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to Go Web Programming")
}

func main() {

	http.HandleFunc("/", index)

	server := &http.Server{
		Addr:         ":8080",
		ReadTimeout:  60 * time.Second,
		WriteTimeout: 60 * time.Second,
	}

	log.Println("Listening...")
	server.ListenAndServe()
}


================================================
FILE: ch08/calc/calc.go
================================================
// Package calc provides a simple calculator
package calc

import "math"

// Sum returns sum of integer values
func Sum(nums ...int) int {
	result := 0
	for _, v := range nums {
		result += v
	}
	return result
}

// Average returns average of integer values
// The output provides a float64 value in two decimal points
func Average(nums ...int) float64 {
	sum := 0
	for _, v := range nums {
		sum += v
	}
	result := float64(sum) / float64(len(nums))
	pow := math.Pow(10, float64(2))
	digit := pow * result
	round := math.Floor(digit)
	return round / pow

}


================================================
FILE: ch08/calc/calc_test.go
================================================
package calc

import (
	"fmt"
	"testing"
	"time"
)

// Test case for the function Sum
func TestSum(t *testing.T) {
	input, expected := []int{7, 8, 10}, 25
	result := Sum(input...)
	if result != expected {

		t.Errorf("Result: %d, Expected: %d", result, expected)
	}

}

// Test case for function Average
func TestAverage(t *testing.T) {
	input, expected := []int{7, 8, 10}, 8.33
	result := Average(input...)
	if result != expected {

		t.Errorf("Result: %f, Expected: %f", result, expected)
	}
}

// Benchmark for function Sum
func BenchmarkSum(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Sum(7, 8, 10)
	}
}

// Benchmark for function Average
func BenchmarkAverage(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Average(7, 8, 10)
	}
}

func TestLongRun(t *testing.T) {
	// Checks whether the short flag is provided
	if testing.Short() {
		t.Skip("Skipping test in short mode")
	}
	// Long running implementation goes here
	time.Sleep(5 * time.Second)
}

// Test case for the function Sum to be executed in parallel
func TestSumInParallel(t *testing.T) {
	t.Parallel()
	// Delaying 1 second for the sake of demonstration
	time.Sleep(1 * time.Second)
	input, expected := []int{7, 8, 10}, 25
	result := Sum(input...)
	if result != expected {

		t.Errorf("Result: %d, Expected: %d", result, expected)
	}

}

// Test case for the function Sum to be executed in parallel
func TestAverageInParallel(t *testing.T) {
	t.Parallel()
	// Delaying 1 second for the sake of demonstration
	time.Sleep(2 * time.Second)
	input, expected := []int{7, 8, 10}, 8.33
	result := Average(input...)
	if result != expected {

		t.Errorf("Result: %f, Expected: %f", result, expected)
	}
}

// Example code for function Sum
func ExampleSum() {
	fmt.Println(Sum(7, 8, 10))
	// Output: 25
}

// Example code for function Average
func ExampleAverage() {
	fmt.Println(Average(7, 8, 10))
	// Output: 8.33
}


================================================
FILE: ch08/httpbdd/controllers/controllers_suite_test.go
================================================
package controllers_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

func TestControllers(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Controllers Suite")
}


================================================
FILE: ch08/httpbdd/controllers/user_controller.go
================================================
package controllers

import (
	"encoding/json"
	"log"
	"net/http"

	"github.com/shijuvar/go-recipes/ch08/httpbdd/model"
)

// GetUsers serves requests for Http Get to "/users"
func GetUsers(store model.UserStore) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		data := store.GetUsers()
		users, err := json.Marshal(data)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(users)
	})

}

// CreateUser serves requests for Http Post to "/users"
func CreateUser(store model.UserStore) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var user model.User
		// Decode the incoming User json
		err := json.NewDecoder(r.Body).Decode(&user)
		if err != nil {
			log.Fatalf("[Controllers.CreateUser]: %s\n", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		// Insert User entity into User Store
		err = store.AddUser(user)
		if err != nil {
			if err == model.ErrorEmailExists {
				w.WriteHeader(http.StatusBadRequest)
			} else {
				w.WriteHeader(http.StatusInternalServerError)
			}
			return
		}
		w.WriteHeader(http.StatusCreated)
	})
}


================================================
FILE: ch08/httpbdd/controllers/user_controller_test.go
================================================
package controllers_test

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/shijuvar/go-recipes/ch08/httpbdd/controllers"
	"github.com/shijuvar/go-recipes/ch08/httpbdd/model"

	"github.com/gorilla/mux"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("UserController", func() {
	var r *mux.Router
	var w *httptest.ResponseRecorder
	var store *FakeUserStore
	BeforeEach(func() {
		r = mux.NewRouter()
		store = newFakeUserStore()
	})

	// Specs for HTTP Get to "/users"
	Describe("Get list of Users", func() {
		Context("Get all Users from data store", func() {
			It("Should get list of Users", func() {
				r.Handle("/users", controllers.GetUsers(store)).Methods("GET")
				req, err := http.NewRequest("GET", "/users", nil)
				Expect(err).NotTo(HaveOccurred())
				w = httptest.NewRecorder()
				r.ServeHTTP(w, req)
				Expect(w.Code).To(Equal(200))
				var users []model.User
				json.Unmarshal(w.Body.Bytes(), &users)
				// Verifying mocked data of 2 users
				Expect(len(users)).To(Equal(2))
			})
		})
	})

	// Specs for HTTP Post to "/users"
	Describe("Post a new User", func() {
		Context("Provide a valid User data", func() {
			It("Should create a new User and get HTTP Status: 201", func() {
				r.Handle("/users", controllers.CreateUser(store)).Methods("POST")
				userJson := `{"firstname": "Alex", "lastname": "John", "email": "alex@xyz.com"}`

				req, err := http.NewRequest(
					"POST",
					"/users",
					strings.NewReader(userJson),
				)
				Expect(err).NotTo(HaveOccurred())
				w = httptest.NewRecorder()
				r.ServeHTTP(w, req)
				Expect(w.Code).To(Equal(201))
			})
		})
		Context("Provide a User data that contains duplicate email id", func() {
			It("Should get HTTP Status: 400", func() {
				r.Handle("/users", controllers.CreateUser(store)).Methods("POST")
				userJson := `{"firstname": "Shiju", "lastname": "Varghese", "email": "shiju@xyz.com"}`

				req, err := http.NewRequest(
					"POST",
					"/users",
					strings.NewReader(userJson),
				)
				Expect(err).NotTo(HaveOccurred())
				w = httptest.NewRecorder()
				r.ServeHTTP(w, req)
				Expect(w.Code).To(Equal(400))
			})
		})
	})
})

// FakeUserStore provides a mocked implementation of interface model.UserStore
type FakeUserStore struct {
	userStore []model.User
}

// GetUsers returns all users
func (store *FakeUserStore) GetUsers() []model.User {
	return store.userStore
}

// AddUser inserts a User
func (store *FakeUserStore) AddUser(user model.User) error {
	// Check whether email is exists
	for _, u := range store.userStore {
		if u.Email == user.Email {
			return model.ErrorEmailExists
		}
	}
	store.userStore = append(store.userStore, user)
	return nil
}

// newFakeUserStore provides two dummy data for Users
func newFakeUserStore() *FakeUserStore {
	store := &FakeUserStore{}
	store.AddUser(model.User{
		FirstName: "Shiju",
		LastName:  "Varghese",
		Email:     "shiju@xyz.com",
	})

	store.AddUser(model.User{
		FirstName: "Irene",
		LastName:  "Rose",
		Email:     "irene@xyz.com",
	})
	return store
}


================================================
FILE: ch08/httpbdd/main.go
================================================
package main

import (
	"net/http"

	"github.com/gorilla/mux"

	"github.com/shijuvar/go-recipes/ch08/httpbdd/controllers"
	"github.com/shijuvar/go-recipes/ch08/httpbdd/store"
)

func setUserRoutes() *mux.Router {
	r := mux.NewRouter()
	userStore := &store.MongoUserStore{}
	r.Handle("/users", controllers.CreateUser(userStore)).Methods("POST")
	r.Handle("/users", controllers.GetUsers(userStore)).Methods("GET")
	return r
}

func main() {
	http.ListenAndServe(":8080", setUserRoutes())
}


================================================
FILE: ch08/httpbdd/model/user.go
================================================
package model

import "errors"

// ErrorEmailExists is an error value for duplicate email id
var ErrorEmailExists = errors.New("Email Id is exists")

// User model
type User struct {
	FirstName string `json:"firstname"`
	LastName  string `json:"lastname"`
	Email     string `json:"email"`
}

// UserStore provides a contract for Data Store for User entity
type UserStore interface {
	GetUsers() []User
	AddUser(User) error
}


================================================
FILE: ch08/httpbdd/store/user_store.go
================================================
package store

import (
	"log"
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"

	"github.com/shijuvar/go-recipes/ch08/httpbdd/model"
)

// MongoDB Session
var mgoSession *mgo.Session

// Create a MongoDB Session
func createDBSession() {
	var err error
	mgoSession, err = mgo.DialWithInfo(&mgo.DialInfo{
		Addrs:   []string{"127.0.0.1"},
		Timeout: 60 * time.Second,
	})
	if err != nil {
		log.Fatalf("[createDbSession]: %s\n", err)
	}
}

// Initializes the MongoDB Session
func init() {
	createDBSession()
}

// MongoUserStore provides persistence logic for "users" collection.
type MongoUserStore struct{}

// AddUser insert new User
func (store *MongoUserStore) AddUser(user model.User) error {
	session := mgoSession.Copy()
	defer session.Close()
	userCol := session.DB("userdb").C("users")
	// Check whether email id is exists or not
	var existUser model.User
	err := userCol.Find(bson.M{"email": user.Email}).One(&existUser)
	if err != nil {
		if err == mgo.ErrNotFound { // Email is unique, no records found
		}
	}
	if (model.User{}) != existUser { // there is a user
		return model.ErrorEmailExists
	}
	err = userCol.Insert(user)
	return err
}

// GetUsers returns all documents from the collection.
func (store *MongoUserStore) GetUsers() []model.User {
	session := mgoSession.Copy()
	defer session.Close()
	userCol := session.DB("userdb").C("users")
	var users []model.User
	iter := userCol.Find(nil).Iter()
	result := model.User{}
	for iter.Next(&result) {
		users = append(users, result)
	}
	return users
}


================================================
FILE: ch08/httptest/main.go
================================================
package main

import (
	"encoding/json"
	"net/http"

	"github.com/gorilla/mux"
)

// User model
type User struct {
	FirstName string `json:"firstname"`
	LastName  string `json:"lastname"`
	Email     string `json:"email"`
}

// getUsers serves requests for Http Get to "/users"
func getUsers(w http.ResponseWriter, r *http.Request) {
	data := []User{
		User{
			FirstName: "Shiju",
			LastName:  "Varghese",
			Email:     "shiju@xyz.com",
		},

		User{
			FirstName: "Irene",
			LastName:  "Rose",
			Email:     "irene@xyz.com",
		},
	}
	users, err := json.Marshal(data)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(users)
}

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/users", getUsers).Methods("GET")
	http.ListenAndServe(":8080", r)
}


================================================
FILE: ch08/httptest/main_test.go
================================================
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gorilla/mux"
)

// TestGetUsers test HTTP Get to "/users" using ResponseRecorder
func TestGetUsers(t *testing.T) {
	r := mux.NewRouter()
	r.HandleFunc("/users", getUsers).Methods("GET")
	req, err := http.NewRequest("GET", "/users", nil)
	if err != nil {
		t.Error(err)
	}
	w := httptest.NewRecorder()

	r.ServeHTTP(w, req)
	if w.Code != 200 {
		t.Errorf("HTTP Status expected: 200, got: %d", w.Code)
	}
}

// TestGetUsersWithServer test HTTP Get to "/users" using Server
func TestGetUsersWithServer(t *testing.T) {
	r := mux.NewRouter()
	r.HandleFunc("/users", getUsers).Methods("GET")
	server := httptest.NewServer(r)
	defer server.Close()
	usersURL := fmt.Sprintf("%s/users", server.URL)
	request, err := http.NewRequest("GET", usersURL, nil)

	res, err := http.DefaultClient.Do(request)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Errorf("HTTP Status expected: 200, got: %d", res.StatusCode)
	}
}


================================================
FILE: grpc/client/main.go
================================================
package main

import (
	"io"
	"log"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	pb "github.com/shijuvar/go-recipes/grpc/customer"
)

const (
	address = "localhost:50051"
)

// createCustomer calls the RPC method CreateCustomer of CustomerServer
func createCustomer(client pb.CustomerClient, customer *pb.CustomerRequest) {
	resp, err := client.CreateCustomer(context.Background(), customer)
	if err != nil {
		log.Fatalf("Could not create Customer: %v", err)
	}
	if resp.Success {
		log.Printf("A new Customer has been added with id: %d", resp.Id)
	}
}

// getCustomers calls the RPC method GetCustomers of CustomerServer
func getCustomers(client pb.CustomerClient, filter *pb.CustomerFilter) {
	// calling the streaming API
	stream, err := client.GetCustomers(context.Background(), filter)
	if err != nil {
		log.Fatalf("Error on get customers: %v", err)
	}
	for {
		// Receiving the stream of data 
		customer, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("%v.GetCustomers(_) = _, %v", client, err)
		}
		log.Printf("Customer: %v", customer)
	}
}
func main() {
	// Set up a connection to the gRPC server.
	conn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	// Creates a new CustomerClient
	client := pb.NewCustomerClient(conn)

	customer := &pb.CustomerRequest{
		Id:    101,
		Name:  "Shiju Varghese",
		Email: "shiju@xyz.com",
		Phone: "732-757-2923",
		Addresses: []*pb.CustomerRequest_Address{
			&pb.CustomerRequest_Address{
				Street:            "1 Mission Street",
				City:              "San Francisco",
				State:             "CA",
				Zip:               "94105",
				IsShippingAddress: false,
			},
			&pb.CustomerRequest_Address{
				Street:            "Greenfield",
				City:              "Kochi",
				State:             "KL",
				Zip:               "68356",
				IsShippingAddress: true,
			},
		},
	}

	// Create a new customer
	createCustomer(client, customer)

	customer = &pb.CustomerRequest{
		Id:    102,
		Name:  "Irene Rose",
		Email: "irene@xyz.com",
		Phone: "732-757-2924",
		Addresses: []*pb.CustomerRequest_Address{
			&pb.CustomerRequest_Address{
				Street:            "1 Mission Street",
				City:              "San Francisco",
				State:             "CA",
				Zip:               "94105",
				IsShippingAddress: true,
			},
		},
	}

	// Create a new customer
	createCustomer(client, customer)
	// Filter with an empty Keyword
	filter := &pb.CustomerFilter{Keyword: ""}
	getCustomers(client, filter)
}


================================================
FILE: grpc/customer/customer.pb.go
================================================
// Code generated by protoc-gen-go.
// source: customer.proto
// DO NOT EDIT!

/*
Package customer is a generated protocol buffer package.

It is generated from these files:
	customer.proto

It has these top-level messages:
	CustomerRequest
	CustomerResponse
	CustomerFilter
*/
package customer

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

import (
	context "golang.org/x/net/context"
	grpc "google.golang.org/grpc"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

// Request message for creating a new customer
type CustomerRequest struct {
	Id        int32                      `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
	Name      string                     `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
	Email     string                     `protobuf:"bytes,3,opt,name=email" json:"email,omitempty"`
	Phone     string                     `protobuf:"bytes,4,opt,name=phone" json:"phone,omitempty"`
	Addresses []*CustomerRequest_Address `protobuf:"bytes,5,rep,name=addresses" json:"addresses,omitempty"`
}

func (m *CustomerRequest) Reset()                    { *m = CustomerRequest{} }
func (m *CustomerRequest) String() string            { return proto.CompactTextString(m) }
func (*CustomerRequest) ProtoMessage()               {}
func (*CustomerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

func (m *CustomerRequest) GetAddresses() []*CustomerRequest_Address {
	if m != nil {
		return m.Addresses
	}
	return nil
}

type CustomerRequest_Address struct {
	Street            string `protobuf:"bytes,1,opt,name=street" json:"street,omitempty"`
	City              string `protobuf:"bytes,2,opt,name=city" json:"city,omitempty"`
	State             string `protobuf:"bytes,3,opt,name=state" json:"state,omitempty"`
	Zip               string `protobuf:"bytes,4,opt,name=zip" json:"zip,omitempty"`
	IsShippingAddress bool   `protobuf:"varint,5,opt,name=isShippingAddress" json:"isShippingAddress,omitempty"`
}

func (m *CustomerRequest_Address) Reset()                    { *m = CustomerRequest_Address{} }
func (m *CustomerRequest_Address) String() string            { return proto.CompactTextString(m) }
func (*CustomerRequest_Address) ProtoMessage()               {}
func (*CustomerRequest_Address) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }

type CustomerResponse struct {
	Id      int32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
	Success bool  `protobuf:"varint,2,opt,name=success" json:"success,omitempty"`
}

func (m *CustomerResponse) Reset()                    { *m = CustomerResponse{} }
func (m *CustomerResponse) String() string            { return proto.CompactTextString(m) }
func (*CustomerResponse) ProtoMessage()               {}
func (*CustomerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }

type CustomerFilter struct {
	Keyword string `protobuf:"bytes,1,opt,name=keyword" json:"keyword,omitempty"`
}

func (m *CustomerFilter) Reset()                    { *m = CustomerFilter{} }
func (m *CustomerFilter) String() string            { return proto.CompactTextString(m) }
func (*CustomerFilter) ProtoMessage()               {}
func (*CustomerFilter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }

func init() {
	proto.RegisterType((*CustomerRequest)(nil), "customer.CustomerRequest")
	proto.RegisterType((*CustomerRequest_Address)(nil), "customer.CustomerRequest.Address")
	proto.RegisterType((*CustomerResponse)(nil), "customer.CustomerResponse")
	proto.RegisterType((*CustomerFilter)(nil), "customer.CustomerFilter")
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion3

// Client API for Customer service

type CustomerClient interface {
	// Get all Customers with filter - A server-to-client streaming RPC.
	GetCustomers(ctx context.Context, in *CustomerFilter, opts ...grpc.CallOption) (Customer_GetCustomersClient, error)
	// Create a new Customer - A simple RPC
	CreateCustomer(ctx context.Context, in *CustomerRequest, opts ...grpc.CallOption) (*CustomerResponse, error)
}

type customerClient struct {
	cc *grpc.ClientConn
}

func NewCustomerClient(cc *grpc.ClientConn) CustomerClient {
	return &customerClient{cc}
}

func (c *customerClient) GetCustomers(ctx context.Context, in *CustomerFilter, opts ...grpc.CallOption) (Customer_GetCustomersClient, error) {
	stream, err := grpc.NewClientStream(ctx, &_Customer_serviceDesc.Streams[0], c.cc, "/customer.Customer/GetCustomers", opts...)
	if err != nil {
		return nil, err
	}
	x := &customerGetCustomersClient{stream}
	if err := x.ClientStream.SendMsg(in); err != nil {
		return nil, err
	}
	if err := x.ClientStream.CloseSend(); err != nil {
		return nil, err
	}
	return x, nil
}

type Customer_GetCustomersClient interface {
	Recv() (*CustomerRequest, error)
	grpc.ClientStream
}

type customerGetCustomersClient struct {
	grpc.ClientStream
}

func (x *customerGetCustomersClient) Recv() (*CustomerRequest, error) {
	m := new(CustomerRequest)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

func (c *customerClient) CreateCustomer(ctx context.Context, in *CustomerRequest, opts ...grpc.CallOption) (*CustomerResponse, error) {
	out := new(CustomerResponse)
	err := grpc.Invoke(ctx, "/customer.Customer/CreateCustomer", in, out, c.cc, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// Server API for Customer service

type CustomerServer interface {
	// Get all Customers with filter - A server-to-client streaming RPC.
	GetCustomers(*CustomerFilter, Customer_GetCustomersServer) error
	// Create a new Customer - A simple RPC
	CreateCustomer(context.Context, *CustomerRequest) (*CustomerResponse, error)
}

func RegisterCustomerServer(s *grpc.Server, srv CustomerServer) {
	s.RegisterService(&_Customer_serviceDesc, srv)
}

func _Customer_GetCustomers_Handler(srv interface{}, stream grpc.ServerStream) error {
	m := new(CustomerFilter)
	if err := stream.RecvMsg(m); err != nil {
		return err
	}
	return srv.(CustomerServer).GetCustomers(m, &customerGetCustomersServer{stream})
}

type Customer_GetCustomersServer interface {
	Send(*CustomerRequest) error
	grpc.ServerStream
}

type customerGetCustomersServer struct {
	grpc.ServerStream
}

func (x *customerGetCustomersServer) Send(m *CustomerRequest) error {
	return x.ServerStream.SendMsg(m)
}

func _Customer_CreateCustomer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(CustomerRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(CustomerServer).CreateCustomer(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/customer.Customer/CreateCustomer",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(CustomerServer).CreateCustomer(ctx, req.(*CustomerRequest))
	}
	return interceptor(ctx, in, info, handler)
}

var _Customer_serviceDesc = grpc.ServiceDesc{
	ServiceName: "customer.Customer",
	HandlerType: (*CustomerServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "CreateCustomer",
			Handler:    _Customer_CreateCustomer_Handler,
		},
	},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "GetCustomers",
			Handler:       _Customer_GetCustomers_Handler,
			ServerStreams: true,
		},
	},
	Metadata: fileDescriptor0,
}

func init() { proto.RegisterFile("customer.proto", fileDescriptor0) }

var fileDescriptor0 = []byte{
	// 326 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x92, 0xef, 0x4a, 0xc3, 0x30,
	0x10, 0xc0, 0x97, 0x6e, 0xdd, 0x9f, 0x53, 0xea, 0x0c, 0x22, 0xb1, 0x9f, 0x6a, 0x3f, 0x15, 0x91,
	0x21, 0xf3, 0xab, 0x20, 0x32, 0x70, 0xf8, 0xb5, 0x3e, 0x41, 0x6d, 0x0f, 0x17, 0xdc, 0xda, 0x9a,
	0xcb, 0x90, 0xf9, 0x0a, 0xbe, 0x83, 0xcf, 0xe0, 0x23, 0x4a, 0xd2, 0x66, 0x03, 0xe7, 0xbe, 0xdd,
	0xef, 0x72, 0x77, 0xf9, 0xe5, 0x08, 0x04, 0xf9, 0x9a, 0x74, 0xb5, 0x42, 0x35, 0xa9, 0x55, 0xa5,
	0x2b, 0x3e, 0x74, 0x1c, 0xff, 0x78, 0x70, 0x32, 0x6b, 0x21, 0xc5, 0xf7, 0x35, 0x92, 0xe6, 0x01,
	0x78, 0xb2, 0x10, 0x2c, 0x62, 0x89, 0x9f, 0x7a, 0xb2, 0xe0, 0x1c, 0x7a, 0x65, 0xb6, 0x42, 0xe1,
	0x45, 0x2c, 0x19, 0xa5, 0x36, 0xe6, 0x67, 0xe0, 0xe3, 0x2a, 0x93, 0x4b, 0xd1, 0xb5, 0xc9, 0x06,
	0x4c, 0xb6, 0x5e, 0x54, 0x25, 0x8a, 0x5e, 0x93, 0xb5, 0xc0, 0xef, 0x61, 0x94, 0x15, 0x85, 0x42,
	0x22, 0x24, 0xe1, 0x47, 0xdd, 0xe4, 0x68, 0x7a, 0x39, 0xd9, 0x1a, 0xfd, 0xb9, 0x7d, 0xf2, 0xd0,
	0x94, 0xa6, 0xbb, 0x9e, 0xf0, 0x8b, 0xc1, 0xa0, 0x4d, 0xf3, 0x73, 0xe8, 0x93, 0x56, 0x88, 0xda,
	0x0a, 0x8e, 0xd2, 0x96, 0x8c, 0x64, 0x2e, 0xf5, 0xc6, 0x49, 0x9a, 0xd8, 0xe8, 0x90, 0xce, 0x34,
	0x3a, 0x49, 0x0b, 0x7c, 0x0c, 0xdd, 0x4f, 0x59, 0xb7, 0x8a, 0x26, 0xe4, 0xd7, 0x70, 0x2a, 0xe9,
	0x79, 0x21, 0xeb, 0x5a, 0x96, 0xaf, 0xed, 0x45, 0xc2, 0x8f, 0x58, 0x32, 0x4c, 0xf7, 0x0f, 0xe2,
	0x3b, 0x18, 0xef, 0x9c, 0xa9, 0xae, 0x4a, 0xc2, 0xbd, 0x95, 0x09, 0x18, 0xd0, 0x3a, 0xcf, 0xcd,
	0x1c, 0xcf, 0xce, 0x71, 0x18, 0x5f, 0x41, 0xe0, 0xba, 0x1f, 0xe5, 0x52, 0xa3, 0x32, 0xb5, 0x6f,
	0xb8, 0xf9, 0xa8, 0x54, 0xd1, 0x3e, 0xc9, 0xe1, 0xf4, 0x9b, 0xc1, 0xd0, 0x15, 0xf3, 0x39, 0x1c,
	0xcf, 0x51, 0x3b, 0x24, 0x2e, 0xf6, 0x57, 0xd8, 0x0c, 0x0c, 0x2f, 0x0e, 0x2e, 0x37, 0xee, 0xdc,
	0x30, 0xfe, 0x04, 0xc1, 0x4c, 0x61, 0xa6, 0x71, 0x3b, 0xfa, 0x70, 0x43, 0x18, 0xfe, 0x77, 0xd4,
	0x3c, 0x3a, 0xee, 0xbc, 0xf4, 0xed, 0x77, 0xba, 0xfd, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xde, 0x91,
	0xd3, 0x62, 0x60, 0x02, 0x00, 0x00,
}


================================================
FILE: grpc/customer/customer.proto
================================================
syntax = "proto3";
package customer;


// The Customer service definition.
service Customer {   
  // Get all Customers with filter - A server-to-client streaming RPC.
  rpc GetCustomers(CustomerFilter) returns (stream CustomerRequest) {}
  // Create a new Customer - A simple RPC 
  rpc CreateCustomer (CustomerRequest) returns (CustomerResponse) {}
}

// Request message for creating a new customer
message CustomerRequest {
  int32 id = 1;  // Unique ID number for a Customer.
  string name = 2;
  string email = 3;
  string phone= 4;
  
  message Address {
    string street = 1;
    string city = 2;
    string state = 3;
    string zip = 4;
    bool isShippingAddress = 5; 
  }

  repeated Address addresses = 5;
}

message CustomerResponse {
  int32 id = 1;
  bool success = 2;
}
message CustomerFilter {    
  string keyword = 1;
}

================================================
FILE: grpc/server/main.go
================================================
package main

import (
	"log"
	"net"
	"strings"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	pb "github.com/shijuvar/go-recipes/grpc/customer"
)

const (
	port = ":50051"
)

// server is used to implement customer.CustomerServer.
type server struct {
	savedCustomers []*pb.CustomerRequest
}

// CreateCustomer creates a new Customer
func (s *server) CreateCustomer(ctx context.Context, in *pb.CustomerRequest) (*pb.CustomerResponse, error) {
	s.savedCustomers = append(s.savedCustomers, in)
	return &pb.CustomerResponse{Id: in.Id, Success: true}, nil
}

// GetCustomers returns all customers by given filter
func (s *server) GetCustomers(filter *pb.CustomerFilter, stream pb.Customer_GetCustomersServer) error {
	for _, customer := range s.savedCustomers {
		if filter.Keyword != "" {
			if !strings.Contains(customer.Name, filter.Keyword) {
				continue
			}
		}
		if err := stream.Send(customer); err != nil {
			return err
		}
	}
	return nil
}

func main() {
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	// Creates a new gRPC server
	s := grpc.NewServer()
	pb.RegisterCustomerServer(s, &server{})
	s.Serve(lis)
}
Download .txt
gitextract_fqtkzqqz/

├── .gitignore
├── LICENSE
├── README.md
├── binarypkg/
│   ├── src/
│   │   └── github.com/
│   │       └── shijuvar/
│   │           └── binarypkg/
│   │               └── utils.go
│   └── utils.go
├── binarypkgdemo/
│   └── main.go
├── ch01/
│   ├── declarations/
│   │   ├── enum.go
│   │   ├── main.go
│   │   └── main1.go
│   ├── favorites/
│   │   └── main.go
│   ├── hello/
│   │   └── main.go
│   ├── lib/
│   │   ├── favorites.go
│   │   └── utils.go
│   ├── loop/
│   │   └── main.go
│   ├── strutils/
│   │   └── utils.go
│   ├── strutilsdemo/
│   │   └── main.go
│   ├── typeconv/
│   │   └── main.go
│   └── vetting/
│       └── main.go
├── ch02/
│   ├── arrays/
│   │   └── main.go
│   ├── defer/
│   │   ├── deferfunc.go
│   │   └── panicrecover.go
│   ├── functions/
│   │   ├── calc.go
│   │   ├── closures.go
│   │   ├── swap.go
│   │   └── variadic.go
│   ├── maps/
│   │   ├── main.go
│   │   └── sort_map.go
│   └── slices/
│       ├── append.go
│       ├── append_nilslice.go
│       ├── copy.go
│       ├── iterate.go
│       ├── main.go
│       └── slicing.go
├── ch03/
│   ├── ecommerce/
│   │   ├── main.go
│   │   └── models.go
│   ├── employee/
│   │   └── employee.go
│   ├── person.go
│   └── pointer/
│       └── main.go
├── ch04/
│   ├── channels/
│   │   └── main.go
│   ├── deadlock/
│   │   ├── main.go
│   │   └── main_deadlock.go
│   ├── mathtable/
│   │   └── main.go
│   ├── pipeline/
│   │   ├── main.go
│   │   └── main1.go
│   ├── select/
│   │   ├── context.go
│   │   └── main.go
│   ├── unbuffercounter/
│   │   ├── main.go
│   │   └── main1.go
│   └── worker/
│       └── main.go
├── ch05/
│   ├── archivetar/
│   │   └── main.go
│   ├── archivezip/
│   │   └── main.go
│   ├── cmdflags/
│   │   └── main.go
│   ├── flag/
│   │   └── main.go
│   ├── json/
│   │   └── main.go
│   ├── jsontag/
│   │   └── main.go
│   ├── log/
│   │   ├── logger.go
│   │   └── main.go
│   └── simplelog/
│       └── main.go
├── ch06/
│   ├── influx/
│   │   └── main.go
│   ├── mongo/
│   │   ├── bookmark_store.go
│   │   └── main.go
│   ├── postgres/
│   │   └── main.go
│   └── rethink/
│       ├── bookmark_store.go
│       └── main.go
├── ch07/
│   ├── bookmarkapi/
│   │   ├── common/
│   │   │   ├── auth.go
│   │   │   ├── bootstrapper.go
│   │   │   ├── config.json
│   │   │   ├── logger.go
│   │   │   ├── mongo_utils.go
│   │   │   └── utils.go
│   │   ├── controllers/
│   │   │   ├── bookmark_controller.go
│   │   │   ├── resources.go
│   │   │   └── user_controller.go
│   │   ├── keys/
│   │   │   ├── app.rsa
│   │   │   └── app.rsa.pub
│   │   ├── main.go
│   │   ├── model/
│   │   │   └── models.go
│   │   ├── routers/
│   │   │   ├── bookmark.go
│   │   │   ├── routers.go
│   │   │   └── user.go
│   │   └── store/
│   │       ├── bookmark_store.go
│   │       └── user_store.go
│   ├── customhandler/
│   │   └── main.go
│   ├── defaultservemux/
│   │   └── main.go
│   ├── handlefunc/
│   │   └── main.go
│   ├── handlerfunc/
│   │   └── main.go
│   ├── httpserver/
│   │   └── main.go
│   ├── middleware/
│   │   └── main.go
│   └── server/
│       └── main.go
├── ch08/
│   ├── calc/
│   │   ├── calc.go
│   │   └── calc_test.go
│   ├── httpbdd/
│   │   ├── controllers/
│   │   │   ├── controllers_suite_test.go
│   │   │   ├── user_controller.go
│   │   │   └── user_controller_test.go
│   │   ├── main.go
│   │   ├── model/
│   │   │   └── user.go
│   │   └── store/
│   │       └── user_store.go
│   └── httptest/
│       ├── main.go
│       └── main_test.go
└── grpc/
    ├── client/
    │   └── main.go
    ├── customer/
    │   ├── customer.pb.go
    │   └── customer.proto
    └── server/
        └── main.go
Download .txt
SYMBOL INDEX (362 symbols across 95 files)

FILE: binarypkg/utils.go
  function ToUpperCase (line 6) | func ToUpperCase(s string) string {
  function ToLowerCase (line 11) | func ToLowerCase(s string) string {

FILE: binarypkgdemo/main.go
  function main (line 9) | func main() {

FILE: ch01/declarations/enum.go
  constant UNSPECIFIED (line 7) | UNSPECIFIED Level = iota
  constant TRACE (line 9) | TRACE
  constant INFO (line 11) | INFO
  constant WARNING (line 13) | WARNING
  constant ERROR (line 15) | ERROR
  type Level (line 19) | type Level
    method String (line 31) | func (l Level) String() string {
  function main (line 35) | func main() {

FILE: ch01/declarations/main.go
  constant Title (line 6) | Title = "Person Details"
  function main (line 11) | func main() {

FILE: ch01/declarations/main1.go
  constant Title (line 6) | Title string = "Person Details"
  function main (line 11) | func main() {

FILE: ch01/favorites/main.go
  function main (line 9) | func main() {

FILE: ch01/hello/main.go
  function main (line 5) | func main() {

FILE: ch01/lib/favorites.go
  function init (line 7) | func init() {
  function Add (line 15) | func Add(favorite string) {
  function GetAll (line 20) | func GetAll() []string {

FILE: ch01/lib/utils.go
  function PrintFavorites (line 8) | func PrintFavorites() {

FILE: ch01/loop/main.go
  function main (line 5) | func main() {
  function sum (line 9) | func sum() {
  function sum1 (line 16) | func sum1() {

FILE: ch01/strutils/utils.go
  function ToUpperCase (line 10) | func ToUpperCase(s string) string {
  function ToLowerCase (line 15) | func ToLowerCase(s string) string {
  function ToFirstUpper (line 20) | func ToFirstUpper(s string) string {

FILE: ch01/strutilsdemo/main.go
  function main (line 9) | func main() {

FILE: ch01/typeconv/main.go
  function main (line 8) | func main() {

FILE: ch01/vetting/main.go
  function main (line 5) | func main() {

FILE: ch02/arrays/main.go
  function main (line 7) | func main() {

FILE: ch02/defer/deferfunc.go
  function ReadFile (line 9) | func ReadFile(filename string) ([]byte, error) {
  function main (line 18) | func main() {

FILE: ch02/defer/panicrecover.go
  function panicRecover (line 7) | func panicRecover() {
  function main (line 21) | func main() {

FILE: ch02/functions/calc.go
  function Add (line 7) | func Add(x, y int) int {
  function Subtract (line 11) | func Subtract(x, y int) int {
  function main (line 15) | func main() {

FILE: ch02/functions/closures.go
  function SplitValues (line 7) | func SplitValues(f func(sum int) (int, int)) {
  function main (line 15) | func main() {

FILE: ch02/functions/swap.go
  function Swap (line 7) | func Swap(x, y string) (string, string) {
  function main (line 11) | func main() {

FILE: ch02/functions/variadic.go
  function Sum (line 7) | func Sum(nums ...int) int {
  function main (line 15) | func main() {

FILE: ch02/maps/main.go
  function main (line 7) | func main() {
  function removeLan (line 48) | func removeLan(langs map[string]string, key string) {

FILE: ch02/maps/sort_map.go
  function main (line 8) | func main() {

FILE: ch02/slices/append.go
  function main (line 7) | func main() {

FILE: ch02/slices/append_nilslice.go
  function main (line 5) | func main() {

FILE: ch02/slices/copy.go
  function main (line 7) | func main() {

FILE: ch02/slices/iterate.go
  function main (line 7) | func main() {

FILE: ch02/slices/main.go
  function main (line 7) | func main() {

FILE: ch02/slices/slicing.go
  function main (line 7) | func main() {

FILE: ch03/ecommerce/main.go
  function main (line 8) | func main() {

FILE: ch03/ecommerce/models.go
  type Address (line 8) | type Address struct
  type Customer (line 13) | type Customer struct
    method ToString (line 18) | func (c Customer) ToString() string {
    method ShippingAddress (line 21) | func (c Customer) ShippingAddress() string {
  type Order (line 30) | type Order struct
    method GrandTotal (line 38) | func (o *Order) GrandTotal() float64 {
    method ToString (line 45) | func (o *Order) ToString() string {
    method ChangeStatus (line 58) | func (o *Order) ChangeStatus(newStatus string) {
  type OrderItem (line 62) | type OrderItem struct
    method Total (line 67) | func (item OrderItem) Total() float64 {
    method ToString (line 70) | func (item OrderItem) ToString() string {
  type Product (line 77) | type Product struct

FILE: ch03/employee/employee.go
  type TeamMember (line 9) | type TeamMember interface
  type Employee (line 14) | type Employee struct
    method PrintName (line 20) | func (e Employee) PrintName() {
    method PrintDetails (line 24) | func (e Employee) PrintDetails() {
  type Developer (line 28) | type Developer struct
    method PrintDetails (line 34) | func (d Developer) PrintDetails() {
  type Manager (line 43) | type Manager struct
    method PrintDetails (line 50) | func (m Manager) PrintDetails() {
  type Team (line 63) | type Team struct
    method PrintTeamDetails (line 68) | func (t Team) PrintTeamDetails() {
  function main (line 77) | func main() {

FILE: ch03/person.go
  type Person (line 11) | type Person struct
    method PrintName (line 18) | func (p Person) PrintName() {
    method PrintDetails (line 23) | func (p Person) PrintDetails() {
  function main (line 27) | func main() {

FILE: ch03/pointer/main.go
  type Person (line 10) | type Person struct
    method PrintName (line 17) | func (p *Person) PrintName() {
    method PrintDetails (line 22) | func (p *Person) PrintDetails() {
    method ChangeLocation (line 27) | func (p *Person) ChangeLocation(newLocation string) {
  function main (line 30) | func main() {

FILE: ch04/channels/main.go
  function main (line 7) | func main() {

FILE: ch04/deadlock/main.go
  function main (line 7) | func main() {

FILE: ch04/deadlock/main_deadlock.go
  function main (line 7) | func main() {

FILE: ch04/mathtable/main.go
  function main (line 14) | func main() {
  function addTable (line 29) | func addTable() {
  function multiTable (line 43) | func multiTable() {

FILE: ch04/pipeline/main.go
  type fibvalue (line 10) | type fibvalue struct
  function randomCounter (line 16) | func randomCounter(out chan<- int) {
  function generateFibonacci (line 26) | func generateFibonacci(out chan<- fibvalue, in <-chan int) {
  function printFibonacci (line 43) | func printFibonacci(in <-chan fibvalue) {
  function main (line 50) | func main() {

FILE: ch04/pipeline/main1.go
  type fibvalue (line 10) | type fibvalue struct
  function randomCounter (line 17) | func randomCounter(out chan int) {
  function generateFibonacci (line 28) | func generateFibonacci(out chan fibvalue, in chan int) {
  function printFibonacci (line 46) | func printFibonacci(in chan fibvalue) {
  function main (line 53) | func main() {

FILE: ch04/select/context.go
  function generateValues (line 8) | func generateValues(ctx context.Context, counter chan int) {
  function main (line 20) | func main() {

FILE: ch04/select/main.go
  type fibvalue (line 11) | type fibvalue struct
  type squarevalue (line 14) | type squarevalue struct
  function generateSquare (line 19) | func generateSquare(sqrs chan<- squarevalue) {
  function generateFibonacci (line 29) | func generateFibonacci(fibs chan<- fibvalue) {
  function printValues (line 43) | func printValues(fibs <-chan fibvalue, sqrs <-chan squarevalue) {
  function main (line 58) | func main() {

FILE: ch04/unbuffercounter/main.go
  function main (line 12) | func main() {
  function printCounts (line 31) | func printCounts(label string, count chan int) {

FILE: ch04/unbuffercounter/main1.go
  function main (line 12) | func main() {
  function printCounts (line 31) | func printCounts(label string, count chan int) {

FILE: ch04/worker/main.go
  type Task (line 13) | type Task struct
    method Run (line 20) | func (t *Task) Run() {
  constant noOfWorkers (line 31) | noOfWorkers = 3
  function main (line 34) | func main() {
  function worker (line 63) | func worker(taskQueue <-chan *Task, workerId int) {

FILE: ch05/archivetar/main.go
  function addToArchive (line 13) | func addToArchive(filename string, tw *tar.Writer) error {
  function archiveFiles (line 46) | func archiveFiles(files []string, archive string) error {
  function readArchive (line 70) | func readArchive(archive string) error {
  function main (line 106) | func main() {

FILE: ch05/archivezip/main.go
  function addToArchive (line 12) | func addToArchive(filename string, zw *zip.Writer) error {
  function archiveFiles (line 33) | func archiveFiles(files []string, archive string) error {
  function readArchive (line 55) | func readArchive(archive string) error {
  function main (line 84) | func main() {

FILE: ch05/cmdflags/main.go
  function main (line 8) | func main() {

FILE: ch05/flag/main.go
  function main (line 8) | func main() {

FILE: ch05/json/main.go
  type Employee (line 9) | type Employee struct
  function main (line 14) | func main() {

FILE: ch05/jsontag/main.go
  type Employee (line 9) | type Employee struct
  function main (line 16) | func main() {

FILE: ch05/log/logger.go
  constant UNSPECIFIED (line 12) | UNSPECIFIED Level = iota
  constant TRACE (line 14) | TRACE
  constant INFO (line 16) | INFO
  constant WARNING (line 18) | WARNING
  constant ERROR (line 20) | ERROR
  type Level (line 24) | type Level
  function initLog (line 35) | func initLog(
  function SetLogLevel (line 57) | func SetLogLevel(level Level) {

FILE: ch05/log/main.go
  function main (line 8) | func main() {
  function loop (line 22) | func loop() {

FILE: ch05/simplelog/main.go
  function initLog (line 20) | func initLog(
  function main (line 37) | func main() {
  function loop (line 45) | func loop() {

FILE: ch06/influx/main.go
  constant DB (line 16) | DB       = "metricsdb"
  constant username (line 17) | username = "opsadmin"
  constant password (line 18) | password = "pass123"
  function main (line 21) | func main() {
  function influxDBClient (line 38) | func influxDBClient() client.Client {
  function createMetrics (line 51) | func createMetrics(clnt client.Client) {
  function queryDB (line 92) | func queryDB(clnt client.Client, command string) (res []client.Result, e...
  function readWithLimit (line 111) | func readWithLimit(clnt client.Client, limit int) {
  function meanCPUUsage (line 129) | func meanCPUUsage(clnt client.Client, region string) {
  function countRegion (line 144) | func countRegion(clnt client.Client, region string) {

FILE: ch06/mongo/bookmark_store.go
  type Bookmark (line 11) | type Bookmark struct
  type BookmarkStore (line 20) | type BookmarkStore struct
    method Create (line 25) | func (store BookmarkStore) Create(b *Bookmark) error {
    method Update (line 33) | func (store BookmarkStore) Update(b Bookmark) error {
    method Delete (line 47) | func (store BookmarkStore) Delete(id string) error {
    method GetAll (line 53) | func (store BookmarkStore) GetAll() []Bookmark {
    method GetByID (line 64) | func (store BookmarkStore) GetByID(id string) (Bookmark, error) {
    method GetByTag (line 71) | func (store BookmarkStore) GetByTag(tags []string) []Bookmark {

FILE: ch06/mongo/main.go
  function init (line 15) | func init() {
  function createUpdate (line 31) | func createUpdate() {
  function getByID (line 73) | func getByID(id string) {
  function getAll (line 83) | func getAll() {
  function getByTags (line 96) | func getByTags() {
  function delete (line 113) | func delete() {
  function main (line 122) | func main() {

FILE: ch06/postgres/main.go
  type Product (line 12) | type Product struct
  function init (line 21) | func init() {
  function main (line 28) | func main() {
  function createProduct (line 43) | func createProduct(prd Product) {
  function getProducts (line 55) | func getProducts() {
  function getProductByID (line 84) | func getProductByID(id int) {

FILE: ch06/rethink/bookmark_store.go
  type Bookmark (line 10) | type Bookmark struct
  type BookmarkStore (line 19) | type BookmarkStore struct
    method Create (line 24) | func (store BookmarkStore) Create(b *Bookmark) error {
    method Update (line 35) | func (store BookmarkStore) Update(b Bookmark) error {
    method Delete (line 49) | func (store BookmarkStore) Delete(id string) error {
    method GetAll (line 55) | func (store BookmarkStore) GetAll() ([]Bookmark, error) {
    method GetByID (line 64) | func (store BookmarkStore) GetByID(id string) (Bookmark, error) {

FILE: ch06/rethink/main.go
  function initDB (line 15) | func initDB(session *r.Session) {
  function changeFeeds (line 30) | func changeFeeds(session *r.Session) {
  function init (line 50) | func init() {
  function createUpdate (line 72) | func createUpdate() {
  function getByID (line 113) | func getByID(id string) {
  function getAll (line 122) | func getAll() {
  function delete (line 138) | func delete() {
  function main (line 150) | func main() {

FILE: ch07/bookmarkapi/common/auth.go
  type AppClaims (line 18) | type AppClaims struct
  constant privKeyPath (line 28) | privKeyPath = "keys/app.rsa"
  constant pubKeyPath (line 30) | pubKeyPath = "keys/app.rsa.pub"
  function initKeys (line 41) | func initKeys() {
  function GenerateJWT (line 65) | func GenerateJWT(name, role string) (string, error) {
  function AuthorizeRequest (line 84) | func AuthorizeRequest(next http.Handler) http.Handler {
  function AuthorizeRequestWithNegroni (line 144) | func AuthorizeRequestWithNegroni(w http.ResponseWriter, r *http.Request,...
  function TokenFromAuthHeader (line 202) | func TokenFromAuthHeader(r *http.Request) (string, error) {

FILE: ch07/bookmarkapi/common/bootstrapper.go
  function StartUp (line 4) | func StartUp() {

FILE: ch07/bookmarkapi/common/logger.go
  constant UNSPECIFIED (line 12) | UNSPECIFIED Level = iota
  constant TRACE (line 14) | TRACE
  constant INFO (line 16) | INFO
  constant WARNING (line 18) | WARNING
  constant ERROR (line 20) | ERROR
  type Level (line 24) | type Level
  function initLog (line 35) | func initLog(
  function setLogLevel (line 57) | func setLogLevel(level Level) {

FILE: ch07/bookmarkapi/common/mongo_utils.go
  function getSession (line 13) | func getSession() *mgo.Session {
  function createDBSession (line 28) | func createDBSession() {
  function addIndexes (line 42) | func addIndexes() {
  type DataStore (line 62) | type DataStore struct
    method Close (line 68) | func (ds *DataStore) Close() {
    method Collection (line 73) | func (ds *DataStore) Collection(name string) *mgo.Collection {
  function NewDataStore (line 78) | func NewDataStore() *DataStore {

FILE: ch07/bookmarkapi/common/utils.go
  type appError (line 11) | type appError struct
  type errorResource (line 16) | type errorResource struct
  type configuration (line 19) | type configuration struct
  function DisplayAppError (line 26) | func DisplayAppError(w http.ResponseWriter, handlerError error, message ...
  function initConfig (line 45) | func initConfig() {
  function loadAppConfig (line 50) | func loadAppConfig() {

FILE: ch07/bookmarkapi/controllers/bookmark_controller.go
  function CreateBookmark (line 17) | func CreateBookmark(w http.ResponseWriter, r *http.Request) {
  function GetBookmarks (line 76) | func GetBookmarks(w http.ResponseWriter, r *http.Request) {
  function GetBookmarkByID (line 99) | func GetBookmarkByID(w http.ResponseWriter, r *http.Request) {
  function GetBookmarksByUser (line 142) | func GetBookmarksByUser(w http.ResponseWriter, r *http.Request) {
  function UpdateBookmark (line 168) | func UpdateBookmark(w http.ResponseWriter, r *http.Request) {
  function DeleteBookmark (line 206) | func DeleteBookmark(w http.ResponseWriter, r *http.Request) {

FILE: ch07/bookmarkapi/controllers/resources.go
  type UserResource (line 10) | type UserResource struct
  type AuthUserResource (line 14) | type AuthUserResource struct
  type BookmarkResource (line 19) | type BookmarkResource struct
  type BookmarksResource (line 23) | type BookmarksResource struct
  type UserModel (line 28) | type UserModel struct
  type AuthUserModel (line 35) | type AuthUserModel struct

FILE: ch07/bookmarkapi/controllers/user_controller.go
  function Register (line 14) | func Register(w http.ResponseWriter, r *http.Request) {
  function Login (line 45) | func Login(w http.ResponseWriter, r *http.Request) {

FILE: ch07/bookmarkapi/main.go
  function main (line 12) | func main() {

FILE: ch07/bookmarkapi/model/models.go
  type User (line 11) | type User struct
  type Bookmark (line 19) | type Bookmark struct

FILE: ch07/bookmarkapi/routers/bookmark.go
  function SetBookmarkRoutes (line 11) | func SetBookmarkRoutes(router *mux.Router) *mux.Router {

FILE: ch07/bookmarkapi/routers/routers.go
  function InitRoutes (line 8) | func InitRoutes() *mux.Router {

FILE: ch07/bookmarkapi/routers/user.go
  function SetUserRoutes (line 10) | func SetUserRoutes(router *mux.Router) *mux.Router {

FILE: ch07/bookmarkapi/store/bookmark_store.go
  type BookmarkStore (line 13) | type BookmarkStore struct
    method Create (line 18) | func (store BookmarkStore) Create(b *model.Bookmark) error {
    method Update (line 27) | func (store BookmarkStore) Update(b model.Bookmark) error {
    method Delete (line 41) | func (store BookmarkStore) Delete(id string) error {
    method GetAll (line 47) | func (store BookmarkStore) GetAll() []model.Bookmark {
    method GetByUser (line 58) | func (store BookmarkStore) GetByUser(user string) []model.Bookmark {
    method GetByID (line 69) | func (store BookmarkStore) GetByID(id string) (model.Bookmark, error) {
    method GetByTag (line 76) | func (store BookmarkStore) GetByTag(tags []string) []model.Bookmark {

FILE: ch07/bookmarkapi/store/user_store.go
  type UserStore (line 12) | type UserStore struct
    method Create (line 17) | func (store UserStore) Create(user model.User, password string) error {
    method Login (line 30) | func (store UserStore) Login(email, password string) (model.User, erro...

FILE: ch07/customhandler/main.go
  type textHandler (line 9) | type textHandler struct
    method ServeHTTP (line 13) | func (th *textHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques...
  type indexHandler (line 17) | type indexHandler struct
    method ServeHTTP (line 20) | func (ih *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque...
  function main (line 42) | func main() {

FILE: ch07/defaultservemux/main.go
  function index (line 9) | func index(w http.ResponseWriter, r *http.Request) {
  function welcome (line 30) | func welcome(w http.ResponseWriter, r *http.Request) {
  function message (line 33) | func message(w http.ResponseWriter, r *http.Request) {
  function main (line 37) | func main() {

FILE: ch07/handlefunc/main.go
  function index (line 9) | func index(w http.ResponseWriter, r *http.Request) {
  function welcome (line 30) | func welcome(w http.ResponseWriter, r *http.Request) {
  function message (line 33) | func message(w http.ResponseWriter, r *http.Request) {
  function main (line 37) | func main() {

FILE: ch07/handlerfunc/main.go
  function textResponseHandler (line 9) | func textResponseHandler(resposeText string) http.Handler {
  function index (line 14) | func index(w http.ResponseWriter, r *http.Request) {
  function welcome (line 35) | func welcome(w http.ResponseWriter, r *http.Request) {
  function message (line 38) | func message(w http.ResponseWriter, r *http.Request) {
  function main (line 42) | func main() {

FILE: ch07/httpserver/main.go
  function handler (line 8) | func handler(w http.ResponseWriter, r *http.Request) {
  function main (line 12) | func main() {

FILE: ch07/middleware/main.go
  function loggingHandler (line 11) | func loggingHandler(next http.Handler) http.Handler {
  function index (line 22) | func index(w http.ResponseWriter, r *http.Request) {
  function welcome (line 43) | func welcome(w http.ResponseWriter, r *http.Request) {
  function message (line 46) | func message(w http.ResponseWriter, r *http.Request) {
  function favicon (line 49) | func favicon(w http.ResponseWriter, r *http.Request) {
  function main (line 52) | func main() {

FILE: ch07/server/main.go
  function index (line 10) | func index(w http.ResponseWriter, r *http.Request) {
  function main (line 14) | func main() {

FILE: ch08/calc/calc.go
  function Sum (line 7) | func Sum(nums ...int) int {
  function Average (line 17) | func Average(nums ...int) float64 {

FILE: ch08/calc/calc_test.go
  function TestSum (line 10) | func TestSum(t *testing.T) {
  function TestAverage (line 21) | func TestAverage(t *testing.T) {
  function BenchmarkSum (line 31) | func BenchmarkSum(b *testing.B) {
  function BenchmarkAverage (line 38) | func BenchmarkAverage(b *testing.B) {
  function TestLongRun (line 44) | func TestLongRun(t *testing.T) {
  function TestSumInParallel (line 54) | func TestSumInParallel(t *testing.T) {
  function TestAverageInParallel (line 68) | func TestAverageInParallel(t *testing.T) {
  function ExampleSum (line 81) | func ExampleSum() {
  function ExampleAverage (line 87) | func ExampleAverage() {

FILE: ch08/httpbdd/controllers/controllers_suite_test.go
  function TestControllers (line 10) | func TestControllers(t *testing.T) {

FILE: ch08/httpbdd/controllers/user_controller.go
  function GetUsers (line 12) | func GetUsers(store model.UserStore) http.Handler {
  function CreateUser (line 28) | func CreateUser(store model.UserStore) http.Handler {

FILE: ch08/httpbdd/controllers/user_controller_test.go
  type FakeUserStore (line 82) | type FakeUserStore struct
    method GetUsers (line 87) | func (store *FakeUserStore) GetUsers() []model.User {
    method AddUser (line 92) | func (store *FakeUserStore) AddUser(user model.User) error {
  function newFakeUserStore (line 104) | func newFakeUserStore() *FakeUserStore {

FILE: ch08/httpbdd/main.go
  function setUserRoutes (line 12) | func setUserRoutes() *mux.Router {
  function main (line 20) | func main() {

FILE: ch08/httpbdd/model/user.go
  type User (line 9) | type User struct
  type UserStore (line 16) | type UserStore interface

FILE: ch08/httpbdd/store/user_store.go
  function createDBSession (line 17) | func createDBSession() {
  function init (line 29) | func init() {
  type MongoUserStore (line 34) | type MongoUserStore struct
    method AddUser (line 37) | func (store *MongoUserStore) AddUser(user model.User) error {
    method GetUsers (line 56) | func (store *MongoUserStore) GetUsers() []model.User {

FILE: ch08/httptest/main.go
  type User (line 11) | type User struct
  function getUsers (line 18) | func getUsers(w http.ResponseWriter, r *http.Request) {
  function main (line 42) | func main() {

FILE: ch08/httptest/main_test.go
  function TestGetUsers (line 13) | func TestGetUsers(t *testing.T) {
  function TestGetUsersWithServer (line 29) | func TestGetUsersWithServer(t *testing.T) {

FILE: grpc/client/main.go
  constant address (line 14) | address = "localhost:50051"
  function createCustomer (line 18) | func createCustomer(client pb.CustomerClient, customer *pb.CustomerReque...
  function getCustomers (line 29) | func getCustomers(client pb.CustomerClient, filter *pb.CustomerFilter) {
  function main (line 47) | func main() {

FILE: grpc/customer/customer.pb.go
  constant _ (line 36) | _ = proto.ProtoPackageIsVersion2
  type CustomerRequest (line 39) | type CustomerRequest struct
    method Reset (line 47) | func (m *CustomerRequest) Reset()                    { *m = CustomerRe...
    method String (line 48) | func (m *CustomerRequest) String() string            { return proto.Co...
    method ProtoMessage (line 49) | func (*CustomerRequest) ProtoMessage()               {}
    method Descriptor (line 50) | func (*CustomerRequest) Descriptor() ([]byte, []int) { return fileDesc...
    method GetAddresses (line 52) | func (m *CustomerRequest) GetAddresses() []*CustomerRequest_Address {
  type CustomerRequest_Address (line 59) | type CustomerRequest_Address struct
    method Reset (line 67) | func (m *CustomerRequest_Address) Reset()                    { *m = Cu...
    method String (line 68) | func (m *CustomerRequest_Address) String() string            { return ...
    method ProtoMessage (line 69) | func (*CustomerRequest_Address) ProtoMessage()               {}
    method Descriptor (line 70) | func (*CustomerRequest_Address) Descriptor() ([]byte, []int) { return ...
  type CustomerResponse (line 72) | type CustomerResponse struct
    method Reset (line 77) | func (m *CustomerResponse) Reset()                    { *m = CustomerR...
    method String (line 78) | func (m *CustomerResponse) String() string            { return proto.C...
    method ProtoMessage (line 79) | func (*CustomerResponse) ProtoMessage()               {}
    method Descriptor (line 80) | func (*CustomerResponse) Descriptor() ([]byte, []int) { return fileDes...
  type CustomerFilter (line 82) | type CustomerFilter struct
    method Reset (line 86) | func (m *CustomerFilter) Reset()                    { *m = CustomerFil...
    method String (line 87) | func (m *CustomerFilter) String() string            { return proto.Com...
    method ProtoMessage (line 88) | func (*CustomerFilter) ProtoMessage()               {}
    method Descriptor (line 89) | func (*CustomerFilter) Descriptor() ([]byte, []int) { return fileDescr...
  function init (line 91) | func init() {
  constant _ (line 104) | _ = grpc.SupportPackageIsVersion3
  type CustomerClient (line 108) | type CustomerClient interface
  type customerClient (line 115) | type customerClient struct
    method GetCustomers (line 123) | func (c *customerClient) GetCustomers(ctx context.Context, in *Custome...
    method CreateCustomer (line 155) | func (c *customerClient) CreateCustomer(ctx context.Context, in *Custo...
  function NewCustomerClient (line 119) | func NewCustomerClient(cc *grpc.ClientConn) CustomerClient {
  type Customer_GetCustomersClient (line 138) | type Customer_GetCustomersClient interface
  type customerGetCustomersClient (line 143) | type customerGetCustomersClient struct
    method Recv (line 147) | func (x *customerGetCustomersClient) Recv() (*CustomerRequest, error) {
  type CustomerServer (line 166) | type CustomerServer interface
  function RegisterCustomerServer (line 173) | func RegisterCustomerServer(s *grpc.Server, srv CustomerServer) {
  function _Customer_GetCustomers_Handler (line 177) | func _Customer_GetCustomers_Handler(srv interface{}, stream grpc.ServerS...
  type Customer_GetCustomersServer (line 185) | type Customer_GetCustomersServer interface
  type customerGetCustomersServer (line 190) | type customerGetCustomersServer struct
    method Send (line 194) | func (x *customerGetCustomersServer) Send(m *CustomerRequest) error {
  function _Customer_CreateCustomer_Handler (line 198) | func _Customer_CreateCustomer_Handler(srv interface{}, ctx context.Conte...
  function init (line 235) | func init() { proto.RegisterFile("customer.proto", fileDescriptor0) }

FILE: grpc/server/main.go
  constant port (line 15) | port = ":50051"
  type server (line 19) | type server struct
    method CreateCustomer (line 24) | func (s *server) CreateCustomer(ctx context.Context, in *pb.CustomerRe...
    method GetCustomers (line 30) | func (s *server) GetCustomers(filter *pb.CustomerFilter, stream pb.Cus...
  function main (line 44) | func main() {
Condensed preview — 103 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (140K chars).
[
  {
    "path": ".gitignore",
    "chars": 294,
    "preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
  },
  {
    "path": "LICENSE",
    "chars": 1081,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2016 Shiju Varghese\n\nPermission is hereby granted, free of charge, to any person ob"
  },
  {
    "path": "README.md",
    "chars": 489,
    "preview": "# Go Recipes\nCode examples for the book \"Go Recipes\" by Apress.\n\n# gokit\nCheck out [github.com/shijuvar/gokit](https://g"
  },
  {
    "path": "binarypkg/src/github.com/shijuvar/binarypkg/utils.go",
    "chars": 44,
    "preview": "//go:binary-only-package\n\npackage binarypkg\n"
  },
  {
    "path": "binarypkg/utils.go",
    "chars": 286,
    "preview": "package binarypkg\n\nimport \"strings\"\n\n// ToUpperCase returns the string changed with upper case.\nfunc ToUpperCase(s strin"
  },
  {
    "path": "binarypkgdemo/main.go",
    "chars": 283,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/shijuvar/go-recipes/binarypkg\"\n)\n\nfunc main() {\n\tstr := \"Golang\"\n\t// Convert"
  },
  {
    "path": "ch01/declarations/enum.go",
    "chars": 675,
    "preview": "package main\n\nimport \"fmt\"\n\nconst (\n\t// UNSPECIFIED logs nothing\n\tUNSPECIFIED Level = iota // 0 :\n\t// TRACE logs everyth"
  },
  {
    "path": "ch01/declarations/main.go",
    "chars": 423,
    "preview": "package main\n\nimport \"fmt\"\n\n// Declare constant\nconst Title = \"Person Details\"\n\n// Declare package variable\nvar Country "
  },
  {
    "path": "ch01/declarations/main1.go",
    "chars": 454,
    "preview": "package main\n\nimport \"fmt\"\n\n// Declare constant\nconst Title string = \"Person Details\"\n\n// Declare package variable\nvar C"
  },
  {
    "path": "ch01/favorites/main.go",
    "chars": 483,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\n\tfav \"github.com/shijuvar/go-recipes/ch01/lib\"\n)\n\nfunc main() {\n\t// Print default favorit"
  },
  {
    "path": "ch01/hello/main.go",
    "chars": 73,
    "preview": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello, World\")\n}\n"
  },
  {
    "path": "ch01/lib/favorites.go",
    "chars": 458,
    "preview": "package lib\n\n// Stores favorites\nvar favorites []string\n\n// Initialization logic for the package\nfunc init() {\n\tfavorite"
  },
  {
    "path": "ch01/lib/utils.go",
    "chars": 132,
    "preview": "package lib\n\nimport (\n\t\"fmt\"\n)\n\n// Print all favorites\nfunc PrintFavorites() {\n\tfor _, v := range favorites {\n\t\tfmt.Prin"
  },
  {
    "path": "ch01/loop/main.go",
    "chars": 219,
    "preview": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tsum()\n\tsum1()\n}\nfunc sum() {\n\tsum := 0\n\tfor i := 0; i < 10; i++ {\n\t\tsum += i\n"
  },
  {
    "path": "ch01/strutils/utils.go",
    "chars": 711,
    "preview": "// Package strutils provides string utility functions\npackage strutils\n\nimport (\n\t\"strings\"\n\t\"unicode\"\n)\n\n// Returns the"
  },
  {
    "path": "ch01/strutilsdemo/main.go",
    "chars": 404,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/shijuvar/go-recipes/ch01/strutils\"\n)\n\nfunc main() {\n\tstr1, str2 := \"Golang\","
  },
  {
    "path": "ch01/typeconv/main.go",
    "chars": 442,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n)\n\nfunc main() {\n\t// type conversion: dealing with a type\n\t// The expression T("
  },
  {
    "path": "ch01/vetting/main.go",
    "chars": 105,
    "preview": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfloatValue:=4.99\n\tfmt.Printf(\"The value is: %d\",floatValue)\n}\n"
  },
  {
    "path": "ch02/arrays/main.go",
    "chars": 1197,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\t// Declare arrays\n\tvar x [5]int\n\t// Assign values at specific index\n\tx[0"
  },
  {
    "path": "ch02/defer/deferfunc.go",
    "chars": 301,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n)\n\nfunc ReadFile(filename string) ([]byte, error) {\n\tf, err := os.Open("
  },
  {
    "path": "ch02/defer/panicrecover.go",
    "chars": 488,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc panicRecover() {\n\n\tdefer fmt.Println(\"Deferred call - 1\")\n\tdefer func() {\n\t\tfmt.Pr"
  },
  {
    "path": "ch02/functions/calc.go",
    "chars": 269,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc Add(x, y int) int {\n\treturn x + y\n}\n\nfunc Subtract(x, y int) int {\n\treturn x - y\n}"
  },
  {
    "path": "ch02/functions/closures.go",
    "chars": 435,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc SplitValues(f func(sum int) (int, int)) {\n\tx, y := f(35)\n\tfmt.Println(x, y)\n\n\tx, y"
  },
  {
    "path": "ch02/functions/swap.go",
    "chars": 225,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc Swap(x, y string) (string, string) {\n\treturn y, x\n}\n\nfunc main() {\n\tx, y := \"Shiju"
  },
  {
    "path": "ch02/functions/variadic.go",
    "chars": 455,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc Sum(nums ...int) int {\n\ttotal := 0\n\tfor _, num := range nums {\n\t\ttotal += num\n\t}\n\t"
  },
  {
    "path": "ch02/maps/main.go",
    "chars": 996,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\t// Declares a nil map\n\tvar chapts map[int]string\n\n\t// Initialize map wit"
  },
  {
    "path": "ch02/maps/sort_map.go",
    "chars": 637,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n)\n\nfunc main() {\n\t// Initialize map with make function\n\tchapts := make(map[int]str"
  },
  {
    "path": "ch02/slices/append.go",
    "chars": 506,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tx := make([]int, 2, 5)\n\tx[0] = 10\n\tx[1] = 20\n\tfmt.Println(\"Slice x:\", x)"
  },
  {
    "path": "ch02/slices/append_nilslice.go",
    "chars": 189,
    "preview": "package main\n\nimport \"fmt\"\n\nfunc main() {\n\t// Declare a nil slice\n\tvar x []int\n\tfmt.Println(x, len(x), cap(x))\n\tx = appe"
  },
  {
    "path": "ch02/slices/copy.go",
    "chars": 392,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tx := []int{10, 20, 30}\n\tfmt.Printf(\"[Slice:x] Length is %d Capacity is %"
  },
  {
    "path": "ch02/slices/iterate.go",
    "chars": 141,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tx := []int{10, 20, 30, 40, 50}\n\tfor k, v := range x {\n\t\tfmt.Printf(\"x[%d"
  },
  {
    "path": "ch02/slices/main.go",
    "chars": 489,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tx := make([]int, 3, 5)\n\tx[0] = 10\n\tx[1] = 20\n\tx[2] = 30\n\tfmt.Println(x)\n"
  },
  {
    "path": "ch02/slices/slicing.go",
    "chars": 375,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\tx := []int{10, 20, 30, 40, 50}\n\ty := x[1:3]\n\tfmt.Println(\"y:\", y)\n\tfmt.P"
  },
  {
    "path": "ch03/ecommerce/main.go",
    "chars": 1267,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc main() {\n\torder := &Order{\n\t\tId: 1001,\n\t\tCustomer: Customer{\n\t\t\tFirstName:"
  },
  {
    "path": "ch03/ecommerce/models.go",
    "chars": 1864,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\ntype Address struct {\n\tStreet, City, State, Zip string\n\tIsShippingAddress      "
  },
  {
    "path": "ch03/employee/employee.go",
    "chars": 2561,
    "preview": "// Example program with Interface, Composition and Method Overriding\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\ntype TeamM"
  },
  {
    "path": "ch03/person.go",
    "chars": 1275,
    "preview": "// Person struct with methods of pointer receiver\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\n// Person struct\ntype Person"
  },
  {
    "path": "ch03/pointer/main.go",
    "chars": 844,
    "preview": "// Person struct with methods of pointer receiver\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\ntype Person struct {\n\tFirstN"
  },
  {
    "path": "ch04/channels/main.go",
    "chars": 734,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\t// Declare a unbuffered channel\n\tcounter := make(chan int)\n\t// Creates a"
  },
  {
    "path": "ch04/deadlock/main.go",
    "chars": 259,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\t// Declare a unbuffered channel\n\tcounter := make(chan int)\n\t// Perform s"
  },
  {
    "path": "ch04/deadlock/main_deadlock.go",
    "chars": 278,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n)\n\nfunc main() {\n\t// Declare a unbuffered channel\n\tcounter := make(chan int)\n\t// This will"
  },
  {
    "path": "ch04/mathtable/main.go",
    "chars": 1269,
    "preview": "// This sample program demonstrates how to create goroutines\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"sync\"\n\t\"time\"\n"
  },
  {
    "path": "ch04/pipeline/main.go",
    "chars": 1128,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"math/rand\"\n\t\"sync\"\n)\n\ntype fibvalue struct {\n\tinput, value int\n}\n\nvar wg sync.Wa"
  },
  {
    "path": "ch04/pipeline/main1.go",
    "chars": 1373,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"math/rand\"\n\t\"sync\"\n)\n\ntype fibvalue struct {\n\tinput, value int\n}\n\nvar wg sync.Wa"
  },
  {
    "path": "ch04/select/context.go",
    "chars": 913,
    "preview": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc generateValues(ctx context.Context, counter chan int) {\n\tn := 1\n\tfor {\n"
  },
  {
    "path": "ch04/select/main.go",
    "chars": 1355,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"math/rand\"\n\t\"sync\"\n)\n\ntype (\n\tfibvalue struct {\n\t\tinput, value int\n\t}\n\tsquareval"
  },
  {
    "path": "ch04/unbuffercounter/main.go",
    "chars": 1068,
    "preview": "// Example program with unbuffered channel\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\n// wg is used to wait for the progra"
  },
  {
    "path": "ch04/unbuffercounter/main1.go",
    "chars": 1167,
    "preview": "// Example program with unbuffered channel\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\n// wg is used to wait for the progra"
  },
  {
    "path": "ch04/worker/main.go",
    "chars": 1649,
    "preview": "// This sample program demonstrates how to use a buffered\n// channel to work on multiple tasks with a predefined number\n"
  },
  {
    "path": "ch05/archivetar/main.go",
    "chars": 3464,
    "preview": "package main\n\nimport (\n\t\"archive/tar\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n)\n\n// addToArchive writes a given file into a .tar file\n"
  },
  {
    "path": "ch05/archivezip/main.go",
    "chars": 2540,
    "preview": "package main\n\nimport (\n\t\"archive/zip\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n)\n\n// addToArchive writes a given file into a zip file.\n"
  },
  {
    "path": "ch05/cmdflags/main.go",
    "chars": 895,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n)\n\nfunc main() {\n\n\tfileName := flag.String(\"filename\", \"logfile\", \"File name for t"
  },
  {
    "path": "ch05/flag/main.go",
    "chars": 609,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n)\n\nfunc main() {\n\n\tstrPtr := flag.String(\"name\", \"Shiju\", \"a string\")\n\tnumbPtr := "
  },
  {
    "path": "ch05/json/main.go",
    "chars": 871,
    "preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// Employee struct\ntype Employee struct {\n\tID                         "
  },
  {
    "path": "ch05/jsontag/main.go",
    "chars": 922,
    "preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// Employee struct with struct tags\ntype Employee struct {\n\tID        "
  },
  {
    "path": "ch05/log/logger.go",
    "chars": 1816,
    "preview": "package main\n\nimport (\n\t\"io\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n)\n\nconst (\n\t// UNSPECIFIED logs nothing\n\tUNSPECIFIED Level = iota"
  },
  {
    "path": "ch05/log/main.go",
    "chars": 651,
    "preview": "package main\n\nimport (\n\t\"errors\"\n\t\"flag\"\n)\n\nfunc main() {\n\t// Parse log level from command line\n\tlogLevel := flag.Int(\"l"
  },
  {
    "path": "ch05/simplelog/main.go",
    "chars": 1126,
    "preview": "package main\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n)\n\n// Package level variables, which are pointer to log"
  },
  {
    "path": "ch06/influx/main.go",
    "chars": 3771,
    "preview": "// Example demo for working with InfluxDB\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"time\"\n\n\tc"
  },
  {
    "path": "ch06/mongo/bookmark_store.go",
    "chars": 2115,
    "preview": "package main\n\nimport (\n\t\"time\"\n\n\t\"gopkg.in/mgo.v2\"\n\t\"gopkg.in/mgo.v2/bson\"\n)\n\n// Bookmark type reperesents the metadata "
  },
  {
    "path": "ch06/mongo/main.go",
    "chars": 3291,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t\"gopkg.in/mgo.v2\"\n)\n\nvar store BookmarkStore\nvar id string\n\n// init will "
  },
  {
    "path": "ch06/postgres/main.go",
    "chars": 2060,
    "preview": "package main\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"log\"\n\n\t_ \"github.com/lib/pq\"\n)\n\n// Product struct provides the data mode"
  },
  {
    "path": "ch06/rethink/bookmark_store.go",
    "chars": 2242,
    "preview": "package main\n\nimport (\n\t\"time\"\n\n\tr \"github.com/dancannon/gorethink\"\n)\n\n// Bookmark type reperesents the metadata of a bo"
  },
  {
    "path": "ch06/rethink/main.go",
    "chars": 3901,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\tr \"github.com/dancannon/gorethink\"\n)\n\nvar store BookmarkStore\nvar id stri"
  },
  {
    "path": "ch07/bookmarkapi/common/auth.go",
    "chars": 4920,
    "preview": "package common\n\nimport (\n\t\"context\"\n\t\"crypto/rsa\"\n\t\"errors\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n\n\tjwt \"gi"
  },
  {
    "path": "ch07/bookmarkapi/common/bootstrapper.go",
    "chars": 367,
    "preview": "package common\n\n// StartUp bootstrapps the application\nfunc StartUp() {\n\t// Initialize AppConfig variable\n\tinitConfig()\n"
  },
  {
    "path": "ch07/bookmarkapi/common/config.json",
    "chars": 164,
    "preview": "{\n  \"Server\"      : \"0.0.0.0:8080\",\n  \"MongoDBHost\" : \"127.0.0.1\",\n  \"MongoDBUser\"\t: \"\",\n  \"MongoDBPwd\"\t: \"\",\n  \"Databas"
  },
  {
    "path": "ch07/bookmarkapi/common/logger.go",
    "chars": 1818,
    "preview": "package common\n\nimport (\n\t\"io\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n)\n\nconst (\n\t// UNSPECIFIED logs nothing\n\tUNSPECIFIED Level = io"
  },
  {
    "path": "ch07/bookmarkapi/common/mongo_utils.go",
    "chars": 1829,
    "preview": "package common\n\nimport (\n\t\"log\"\n\t\"time\"\n\n\t\"gopkg.in/mgo.v2\"\n)\n\nvar session *mgo.Session\n\n// GetSession returns a MongoDB"
  },
  {
    "path": "ch07/bookmarkapi/common/utils.go",
    "chars": 1435,
    "preview": "package common\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n)\n\ntype (\n\tappError struct {\n\t\tError      string `jso"
  },
  {
    "path": "ch07/bookmarkapi/controllers/bookmark_controller.go",
    "chars": 5455,
    "preview": "package controllers\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\n\t\"github.com/gorilla/mux\"\n\t\"gopkg.in/mgo.v2\"\n\t\"gopkg.in/mgo."
  },
  {
    "path": "ch07/bookmarkapi/controllers/resources.go",
    "chars": 967,
    "preview": "package controllers\n\nimport (\n\t\"github.com/shijuvar/go-recipes/ch07/bookmarkapi/model\"\n)\n\n//Models for JSON resources\nty"
  },
  {
    "path": "ch07/bookmarkapi/controllers/user_controller.go",
    "chars": 2462,
    "preview": "package controllers\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\n\t\"github.com/shijuvar/go-recipes/ch07/bookmarkapi/common\"\n\t\""
  },
  {
    "path": "ch07/bookmarkapi/keys/app.rsa",
    "chars": 887,
    "preview": "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQDPSMNALgfEMEDbS3kCLiTlpx0S4tZH1jZLcGF5Pjhc9IuEIf7p\n6obYT1W7urDPWM8JGO1mdx+"
  },
  {
    "path": "ch07/bookmarkapi/keys/app.rsa.pub",
    "chars": 272,
    "preview": "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPSMNALgfEMEDbS3kCLiTlpx0S\n4tZH1jZLcGF5Pjhc9IuEIf7p6obY"
  },
  {
    "path": "ch07/bookmarkapi/main.go",
    "chars": 501,
    "preview": "package main\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\n\t\"github.com/shijuvar/go-recipes/ch07/bookmarkapi/common\"\n\t\"github.com/shijuv"
  },
  {
    "path": "ch07/bookmarkapi/model/models.go",
    "chars": 883,
    "preview": "package model\n\nimport (\n\t\"time\"\n\n\t\"gopkg.in/mgo.v2/bson\"\n)\n\ntype (\n\t// User type represents the registered user.\n\tUser s"
  },
  {
    "path": "ch07/bookmarkapi/routers/bookmark.go",
    "chars": 964,
    "preview": "package routers\n\nimport (\n\t\"github.com/gorilla/mux\"\n\n\t\"github.com/shijuvar/go-recipes/ch07/bookmarkapi/common\"\n\t\"github."
  },
  {
    "path": "ch07/bookmarkapi/routers/routers.go",
    "chars": 340,
    "preview": "package routers\n\nimport (\n\t\"github.com/gorilla/mux\"\n)\n\n// InitRoutes registers all routes for the application.\nfunc Init"
  },
  {
    "path": "ch07/bookmarkapi/routers/user.go",
    "chars": 376,
    "preview": "package routers\n\nimport (\n\t\"github.com/shijuvar/go-recipes/ch07/bookmarkapi/controllers\"\n\n\t\"github.com/gorilla/mux\"\n)\n\n/"
  },
  {
    "path": "ch07/bookmarkapi/store/bookmark_store.go",
    "chars": 2285,
    "preview": "package store\n\nimport (\n\t\"time\"\n\n\t\"gopkg.in/mgo.v2\"\n\t\"gopkg.in/mgo.v2/bson\"\n\n\t\"github.com/shijuvar/go-recipes/ch07/bookm"
  },
  {
    "path": "ch07/bookmarkapi/store/user_store.go",
    "chars": 975,
    "preview": "package store\n\nimport (\n\t\"golang.org/x/crypto/bcrypt\"\n\t\"gopkg.in/mgo.v2\"\n\t\"gopkg.in/mgo.v2/bson\"\n\n\t\"github.com/shijuvar/"
  },
  {
    "path": "ch07/customhandler/main.go",
    "chars": 983,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n)\n\ntype textHandler struct {\n\tresponseText string\n}\n\nfunc (th *textHand"
  },
  {
    "path": "ch07/defaultservemux/main.go",
    "chars": 834,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n)\n\nfunc index(w http.ResponseWriter, r *http.Request) {\n\tw.Header().Set"
  },
  {
    "path": "ch07/handlefunc/main.go",
    "chars": 858,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n)\n\nfunc index(w http.ResponseWriter, r *http.Request) {\n\tw.Header().Set"
  },
  {
    "path": "ch07/handlerfunc/main.go",
    "chars": 1242,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n)\n\nfunc textResponseHandler(resposeText string) http.Handler {\n\treturn "
  },
  {
    "path": "ch07/httpserver/main.go",
    "chars": 217,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprint(w, \"Hell"
  },
  {
    "path": "ch07/middleware/main.go",
    "chars": 1497,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n)\n\n// loggingHandler is an HTTP Middleware that logs HTTP reque"
  },
  {
    "path": "ch07/server/main.go",
    "chars": 388,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n)\n\nfunc index(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fp"
  },
  {
    "path": "ch08/calc/calc.go",
    "chars": 557,
    "preview": "// Package calc provides a simple calculator\npackage calc\n\nimport \"math\"\n\n// Sum returns sum of integer values\nfunc Sum("
  },
  {
    "path": "ch08/calc/calc_test.go",
    "chars": 1875,
    "preview": "package calc\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n)\n\n// Test case for the function Sum\nfunc TestSum(t *testing.T) {\n\tinpu"
  },
  {
    "path": "ch08/httpbdd/controllers/controllers_suite_test.go",
    "chars": 206,
    "preview": "package controllers_test\n\nimport (\n\t. \"github.com/onsi/ginkgo\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"testing\"\n)\n\nfunc TestContr"
  },
  {
    "path": "ch08/httpbdd/controllers/user_controller.go",
    "chars": 1260,
    "preview": "package controllers\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\t\"net/http\"\n\n\t\"github.com/shijuvar/go-recipes/ch08/httpbdd/model\"\n"
  },
  {
    "path": "ch08/httpbdd/controllers/user_controller_test.go",
    "chars": 3077,
    "preview": "package controllers_test\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\n\t\"github.com/shijuvar/g"
  },
  {
    "path": "ch08/httpbdd/main.go",
    "chars": 488,
    "preview": "package main\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gorilla/mux\"\n\n\t\"github.com/shijuvar/go-recipes/ch08/httpbdd/controllers"
  },
  {
    "path": "ch08/httpbdd/model/user.go",
    "chars": 425,
    "preview": "package model\n\nimport \"errors\"\n\n// ErrorEmailExists is an error value for duplicate email id\nvar ErrorEmailExists = erro"
  },
  {
    "path": "ch08/httpbdd/store/user_store.go",
    "chars": 1522,
    "preview": "package store\n\nimport (\n\t\"log\"\n\t\"time\"\n\n\t\"gopkg.in/mgo.v2\"\n\t\"gopkg.in/mgo.v2/bson\"\n\n\t\"github.com/shijuvar/go-recipes/ch0"
  },
  {
    "path": "ch08/httptest/main.go",
    "chars": 868,
    "preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\n\t\"github.com/gorilla/mux\"\n)\n\n// User model\ntype User struct {\n\tFirs"
  },
  {
    "path": "ch08/httptest/main_test.go",
    "chars": 1013,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\t\"github.com/gorilla/mux\"\n)\n\n// TestGetUsers "
  },
  {
    "path": "grpc/client/main.go",
    "chars": 2571,
    "preview": "package main\n\nimport (\n\t\"io\"\n\t\"log\"\n\n\t\"golang.org/x/net/context\"\n\t\"google.golang.org/grpc\"\n\n\tpb \"github.com/shijuvar/go-"
  },
  {
    "path": "grpc/customer/customer.pb.go",
    "chars": 10209,
    "preview": "// Code generated by protoc-gen-go.\n// source: customer.proto\n// DO NOT EDIT!\n\n/*\nPackage customer is a generated protoc"
  },
  {
    "path": "grpc/customer/customer.proto",
    "chars": 839,
    "preview": "syntax = \"proto3\";\npackage customer;\n\n\n// The Customer service definition.\nservice Customer {   \n  // Get all Customers "
  },
  {
    "path": "grpc/server/main.go",
    "chars": 1183,
    "preview": "package main\n\nimport (\n\t\"log\"\n\t\"net\"\n\t\"strings\"\n\n\t\"golang.org/x/net/context\"\n\t\"google.golang.org/grpc\"\n\n\tpb \"github.com/"
  }
]

About this extraction

This page contains the full source code of the shijuvar/go-recipes GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 103 files (119.6 KB), approximately 37.9k tokens, and a symbol index with 362 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!