├── chapter10 ├── 2_godeps │ ├── Godeps │ │ ├── _workspace │ │ │ ├── .gitignore │ │ │ └── src │ │ │ │ ├── github.com │ │ │ │ ├── julienschmidt │ │ │ │ │ └── httprouter │ │ │ │ │ │ └── .travis.yml │ │ │ │ └── go-sql-driver │ │ │ │ │ └── mysql │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── .travis.yml │ │ │ │ │ ├── appengine.go │ │ │ │ │ ├── result.go │ │ │ │ │ └── transaction.go │ │ │ │ └── golang.org │ │ │ │ └── x │ │ │ │ └── image │ │ │ │ └── tiff │ │ │ │ └── buffer_test.go │ │ └── Readme │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ └── show.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ ├── id.go │ └── image_test.go ├── 0_base │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ ├── show.html │ │ │ └── new.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ ├── id.go │ └── image_test.go ├── 1_pkg_web │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ └── show.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ ├── id.go │ └── image_test.go └── examples │ ├── 1_pkg_foo │ ├── main.go │ └── foo │ │ └── foo.go │ └── 2_exporting_values │ ├── main.go │ └── foo │ └── foo.go ├── chapter4 ├── 1_file_server │ ├── assets │ │ └── test.txt │ └── main.go ├── 4_httprouter │ ├── templates │ │ ├── users │ │ │ └── new.html │ │ ├── layout.html │ │ └── index │ │ │ └── home.html │ ├── handle_index.go │ ├── handle_user.go │ ├── auth.go │ └── handle_image.go ├── 3_layouts │ ├── templates │ │ ├── layout.html │ │ └── index │ │ │ └── home.html │ └── main.go └── 2_first_template │ ├── main.go │ ├── templates │ └── index │ │ └── home.html │ └── template.go ├── chapter5 ├── 0_base │ ├── _base │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ └── layout.html │ ├── handle_index.go │ ├── auth.go │ └── main.go ├── 1_router │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ └── layout.html │ ├── handle_index.go │ ├── auth.go │ └── main.go ├── 2_registration │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── layout.html │ │ └── users │ │ │ └── new.html │ ├── handle_index.go │ ├── auth.go │ ├── errors.go │ ├── main.go │ ├── handle_user.go │ ├── id.go │ └── user.go └── 3_user_store │ ├── templates │ ├── index │ │ └── home.html │ ├── layout.html │ └── users │ │ └── new.html │ ├── handle_index.go │ ├── auth.go │ ├── errors.go │ ├── main.go │ ├── id.go │ └── handle_user.go ├── chapter6 ├── 0_base │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── layout.html │ │ └── users │ │ │ └── new.html │ ├── handle_index.go │ ├── auth.go │ ├── errors.go │ ├── main.go │ ├── id.go │ └── handle_user.go ├── 1_new_session │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── layout.html │ │ └── users │ │ │ └── new.html │ ├── data │ │ └── users.json │ ├── handle_index.go │ ├── auth.go │ ├── errors.go │ ├── main.go │ ├── session.go │ └── id.go ├── 2_session_store │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── layout.html │ │ └── users │ │ │ └── new.html │ ├── data │ │ └── sessions.json │ ├── handle_index.go │ ├── auth.go │ ├── errors.go │ ├── main.go │ ├── session.go │ └── id.go ├── 3_require_login │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── layout.html │ │ └── users │ │ │ └── new.html │ ├── data │ │ └── sessions.json │ ├── handle_index.go │ ├── auth.go │ ├── errors.go │ ├── main.go │ └── id.go ├── 4_template_data │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── users │ │ │ └── new.html │ │ └── layout.html │ ├── handle_index.go │ ├── auth.go │ ├── data │ │ └── sessions.json │ ├── errors.go │ ├── main.go │ └── id.go ├── 6_edit_user │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── users │ │ │ └── new.html │ │ └── layout.html │ ├── data │ │ ├── users.json │ │ └── sessions.json │ ├── handle_index.go │ ├── auth.go │ ├── id.go │ └── errors.go └── 5_signing_out_and_in │ ├── templates │ ├── index │ │ └── home.html │ ├── sessions │ │ ├── destroy.html │ │ └── new.html │ ├── users │ │ └── new.html │ └── layout.html │ ├── data │ ├── users.json │ └── sessions.json │ ├── handle_index.go │ ├── auth.go │ ├── id.go │ └── errors.go ├── chapter7 ├── 0_base │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── users │ │ │ └── new.html │ │ └── layout.html │ ├── handle_index.go │ ├── auth.go │ ├── id.go │ └── errors.go ├── 1_mysql │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── users │ │ │ └── new.html │ │ └── layout.html │ ├── image_store.go │ ├── image.go │ ├── handle_index.go │ ├── auth.go │ ├── mysql.go │ ├── id.go │ └── errors.go ├── 2_db_image_store │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── users │ │ │ └── new.html │ │ └── layout.html │ ├── image.go │ ├── handle_index.go │ ├── auth.go │ ├── mysql.go │ ├── id.go │ └── errors.go ├── 3_uploading_images │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ └── users │ │ │ └── new.html │ ├── handle_index.go │ ├── auth.go │ ├── mysql.go │ └── id.go └── 4_displaying_images │ ├── templates │ ├── index │ │ └── home.html │ ├── sessions │ │ ├── destroy.html │ │ └── new.html │ ├── images │ │ ├── index.html │ │ └── show.html │ └── users │ │ ├── show.html │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ └── id.go ├── ig ├── templates │ ├── index │ │ └── home.html │ ├── errors │ │ └── 500.html │ ├── sessions │ │ ├── destroy.html │ │ └── new.html │ ├── images │ │ ├── index.html │ │ ├── show.html │ │ └── new.html │ └── users │ │ ├── show.html │ │ └── new.html ├── data │ ├── images │ │ ├── img_0qlPyyrjrQ.png │ │ └── img_IZ0nStUnWw.png │ └── users.json ├── router.go ├── handle_frontpage.go ├── response.go ├── mysql.go └── id.go ├── chapter8 ├── 0_base │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ ├── show.html │ │ │ └── new.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ └── id.go ├── 1_image_resizing │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ └── show.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ └── id.go └── 2_display_resized │ ├── templates │ ├── index │ │ └── home.html │ ├── sessions │ │ ├── destroy.html │ │ └── new.html │ ├── images │ │ ├── index.html │ │ └── show.html │ └── users │ │ ├── show.html │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ └── id.go ├── chapter9 ├── 0_base │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ ├── show.html │ │ │ └── new.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ └── id.go ├── 2_mock_interface │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ └── show.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ └── id.go ├── 3_http_testing │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ └── show.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ ├── id.go │ └── image_test.go ├── 4_benchmarking │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ └── show.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ ├── id.go │ └── image_test.go ├── 1_simple_input_tests │ ├── templates │ │ ├── index │ │ │ └── home.html │ │ ├── sessions │ │ │ ├── destroy.html │ │ │ └── new.html │ │ ├── images │ │ │ ├── index.html │ │ │ └── show.html │ │ └── users │ │ │ ├── show.html │ │ │ └── new.html │ ├── auth.go │ ├── mysql.go │ ├── handle_index.go │ ├── user_test.go │ └── id.go └── examples │ ├── 1_addition │ └── addition_test.go │ └── 2_wrapper_functions │ └── main.go ├── chapter1 ├── helloworld.go └── starwars.go ├── chapter3 ├── 7-unmarshaling-json │ ├── config.json │ └── main.go ├── 1-hello-world │ └── hello.go ├── 2-extra-headers │ └── main.go ├── 3-time-handler │ └── main.go ├── 8-unknown-json-input │ └── main.go └── 5-html-templates │ └── funcs │ └── main.go ├── README.md └── chapter2 └── markdown.go /chapter10/2_godeps/Godeps/_workspace/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /chapter4/1_file_server/assets/test.txt: -------------------------------------------------------------------------------- 1 | This is a static text file! 2 | -------------------------------------------------------------------------------- /chapter5/0_base/_base: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spbooks/go1/HEAD/chapter5/0_base/_base -------------------------------------------------------------------------------- /chapter5/0_base/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter5/1_router/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter6/0_base/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter7/0_base/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter7/1_mysql/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /ig/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter4/4_httprouter/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |

New User

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter5/2_registration/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter5/3_user_store/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter6/1_new_session/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter6/2_session_store/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter6/3_require_login/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter6/4_template_data/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter7/3_uploading_images/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 |

Home

3 | {{end}} 4 | -------------------------------------------------------------------------------- /ig/data/images/img_0qlPyyrjrQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spbooks/go1/HEAD/ig/data/images/img_0qlPyyrjrQ.png -------------------------------------------------------------------------------- /ig/data/images/img_IZ0nStUnWw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spbooks/go1/HEAD/ig/data/images/img_IZ0nStUnWw.png -------------------------------------------------------------------------------- /chapter10/0_base/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter8/0_base/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter9/0_base/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter1/helloworld.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("Hello World") 7 | } 8 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter10/2_godeps/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter10/examples/1_pkg_foo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "./foo" 4 | 5 | func main() { 6 | foo.PrintFoo() 7 | } 8 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | {{template "images/index" .}} 3 | {{end}} 4 | -------------------------------------------------------------------------------- /ig/templates/errors/500.html: -------------------------------------------------------------------------------- 1 | {{define "errors/500"}} 2 |

An Unexpected Error occurred

3 |

{{.Error}}

4 | {{end}} 5 | -------------------------------------------------------------------------------- /chapter10/examples/1_pkg_foo/foo/foo.go: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | import "fmt" 4 | 5 | func PrintFoo() { 6 | fmt.Println("foo") 7 | } 8 | -------------------------------------------------------------------------------- /chapter10/2_godeps/Godeps/_workspace/src/github.com/julienschmidt/httprouter/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.1 4 | - 1.2 5 | - 1.3 6 | - tip 7 | -------------------------------------------------------------------------------- /chapter10/examples/2_exporting_values/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "./foo" 4 | 5 | func main() { 6 | myBar := foo.NewBar() 7 | myBar.status() 8 | 9 | } 10 | -------------------------------------------------------------------------------- /chapter10/2_godeps/Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /chapter10/2_godeps/Godeps/_workspace/src/github.com/go-sql-driver/mysql/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | Icon? 7 | ehthumbs.db 8 | Thumbs.db 9 | -------------------------------------------------------------------------------- /chapter4/3_layouts/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ yield }} 7 | 8 | 9 | -------------------------------------------------------------------------------- /chapter4/4_httprouter/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ yield }} 7 | 8 | 9 | -------------------------------------------------------------------------------- /chapter10/2_godeps/Godeps/_workspace/src/github.com/go-sql-driver/mysql/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.1 4 | - tip 5 | 6 | before_script: 7 | - mysql -e 'create database gotest;' 8 | -------------------------------------------------------------------------------- /chapter7/1_mysql/image_store.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type ImageStore interface { 4 | Save(image *Image) error 5 | Find(id string) (*Image, error) 6 | FindAll(offset int) ([]Image, error) 7 | FindAllByUser(user *User, offset int) ([]Image, error) 8 | } 9 | -------------------------------------------------------------------------------- /chapter6/2_session_store/data/sessions.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sessions": { 3 | "sess_GBEX1Qx0NXmSgXL1nPDg": { 4 | "Id": "sess_GBEX1Qx0NXmSgXL1nPDg", 5 | "UserId": "usr_CydtIC9KUZG0Cbjx", 6 | "Expiry": "2014-10-16T21:52:36.144147885+13:00" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /chapter6/3_require_login/data/sessions.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sessions": { 3 | "sess_GBEX1Qx0NXmSgXL1nPDg": { 4 | "Id": "sess_GBEX1Qx0NXmSgXL1nPDg", 5 | "UserId": "usr_CydtIC9KUZG0Cbjx", 6 | "Expiry": "2014-10-16T21:52:36.144147885+13:00" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /chapter3/7-unmarshaling-json/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "SiteName": "My Cat Blog", 3 | "SiteUrl": "www.mycatblog.com", 4 | "Database": { 5 | "Name": "cats", 6 | "Host": "localhost", 7 | "Port": 3306, 8 | "Username": "user1", 9 | "Password": "Password1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/1_mysql/image.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | type Image struct { 6 | ID string 7 | UserID string 8 | Name string 9 | Location string 10 | Size int64 11 | CreatedAt time.Time 12 | Description string 13 | } 14 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/image.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | type Image struct { 6 | ID string 7 | UserID string 8 | Name string 9 | Location string 10 | Size int64 11 | CreatedAt time.Time 12 | Description string 13 | } 14 | -------------------------------------------------------------------------------- /ig/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter10/0_base/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter7/0_base/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter7/1_mysql/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter8/0_base/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter9/0_base/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /ig/router.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func NewRouter() *httprouter.Router { 10 | router := httprouter.New() 11 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 12 | return router 13 | } 14 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter10/2_godeps/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter3/1-hello-world/hello.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 10 | fmt.Fprintf(w, "Hello Gopher") 11 | }) 12 | 13 | http.ListenAndServe(":3000", nil) 14 | } 15 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter7/3_uploading_images/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/templates/sessions/destroy.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/destroy"}} 2 |
3 |
4 |

Signed Out

5 |

Thanks, you’re now signed out.

6 |

Login

7 |
8 |
9 | {{end}} 10 | -------------------------------------------------------------------------------- /chapter5/0_base/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter5/1_router/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter6/0_base/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter6/1_new_session/data/users.json: -------------------------------------------------------------------------------- 1 | { 2 | "Users": { 3 | "usr_xddHcUI0OuRlrREv": { 4 | "Id": "usr_xddHcUI0OuRlrREv", 5 | "Email": "mal@mal.co.nz", 6 | "HashedPassword": "$2a$10$1y2ojzbG8lCDR6rkydh4l.Y0cBngvXOlpK7HGnA3X4E9AP3dNmVpy", 7 | "Username": "mal" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /chapter6/6_edit_user/data/users.json: -------------------------------------------------------------------------------- 1 | { 2 | "Users": { 3 | "usr_ZRtM7bsqwge7ooxU": { 4 | "Id": "usr_ZRtM7bsqwge7ooxU", 5 | "Email": "ma1l@mal.co.nz", 6 | "HashedPassword": "$2a$10$MUjtyTQW9blr/vz3hGydN.anyUFdiDUZfHE36.GGgzt4VgJaiGb0W", 7 | "Username": "mal" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /chapter7/0_base/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter7/1_mysql/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter4/4_httprouter/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter4/4_httprouter/handle_user.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleUserNew(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "users/new", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter5/2_registration/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter5/3_user_store/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter6/1_new_session/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter6/2_session_store/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter6/3_require_login/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter6/4_template_data/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/data/users.json: -------------------------------------------------------------------------------- 1 | { 2 | "Users": { 3 | "usr_ZRtM7bsqwge7ooxU": { 4 | "Id": "usr_ZRtM7bsqwge7ooxU", 5 | "Email": "mal@mal.co.nz", 6 | "HashedPassword": "$2a$10$jYF3DAoKVNV/X9jBqDUYXec2wloiq4/yFn5s55E9cce.MAxRT9Pbq", 7 | "Username": "mal" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /chapter6/6_edit_user/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /chapter7/3_uploading_images/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | RenderTemplate(w, r, "index/home", nil) 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # “Level Up Your Web Apps With Go” Code Archive 2 | 3 | This repository contains the code archive for the SitePoint books [Level Up Your Web Apps With Go](https://www.sitepoint.com/premium/books/level-up-your-web-apps-with-go). Please follow along with the book, as some code may not compile without additional information. 4 | -------------------------------------------------------------------------------- /chapter10/0_base/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter5/0_base/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/0_base/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/0_base/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/1_mysql/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter8/0_base/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter9/0_base/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter10/2_godeps/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter4/4_httprouter/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter5/1_router/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter5/3_user_store/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ig/handle_frontpage.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func HandleFrontpage(w http.ResponseWriter, r *http.Request) { 6 | images, err := globalImageStore.FindAll(0) 7 | if err != nil { 8 | panic(err) 9 | } 10 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 11 | "Images": images, 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /chapter2/markdown.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/russross/blackfriday" 7 | ) 8 | 9 | func main() { 10 | markdown := []byte(` 11 | # This is a header 12 | * and 13 | * this 14 | * is 15 | * a 16 | * list 17 | `) 18 | html := blackfriday.MarkdownBasic(markdown) 19 | fmt.Println(string(html)) 20 | } 21 | -------------------------------------------------------------------------------- /chapter5/2_registration/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/1_new_session/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/2_session_store/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/3_require_login/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter6/4_template_data/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter4/1_file_server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | // Simple static webserver: 10 | mux := http.NewServeMux() 11 | mux.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/")))) 12 | 13 | log.Fatal(http.ListenAndServe(":3000", mux)) 14 | } 15 | -------------------------------------------------------------------------------- /chapter4/4_httprouter/handle_image.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func HandleImageNew(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 11 | // Display New Image Form 12 | panic(fmt.Errorf("This should not be reached!")) 13 | } 14 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/3_uploading_images/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/auth.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func AuthenticateRequest(w http.ResponseWriter, r *http.Request) { 6 | // Redirect the user to login if they’re not authenticated 7 | authenticated := false 8 | if !authenticated { 9 | http.Redirect(w, r, "/register", http.StatusFound) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter5/0_base/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func main() { 10 | } 11 | 12 | // Creates a new router 13 | func NewRouter() *httprouter.Router { 14 | router := httprouter.New() 15 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 16 | return router 17 | } 18 | -------------------------------------------------------------------------------- /chapter10/0_base/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter10/2_godeps/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter8/0_base/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/0_base/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter7/3_uploading_images/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func NewMySQLDB(dsn string) (*sql.DB, error) { 12 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 13 | if err != nil { 14 | return nil, err 15 | } 16 | 17 | return db, db.Ping() 18 | } 19 | -------------------------------------------------------------------------------- /ig/response.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func Handle404(w http.ResponseWriter, r *http.Request) { 6 | http.NotFound(w, r) 7 | } 8 | 9 | func RenderError(w http.ResponseWriter, r *http.Request, err error) { 10 | w.WriteHeader(http.StatusInternalServerError) 11 | RenderTemplate(w, r, "errors/500", map[string]interface{}{ 12 | "Error": err.Error(), 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /chapter3/2-extra-headers/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | http.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) { 10 | w.Header().Add("Server", "Go Server") 11 | fmt.Fprintf(w, ` 12 | 13 | 14 | Hello Gopher 15 | 16 | `) 17 | }) 18 | 19 | http.ListenAndServe(":3000", nil) 20 | } 21 | -------------------------------------------------------------------------------- /chapter4/3_layouts/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func main() { 6 | mux := http.NewServeMux() 7 | 8 | mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 9 | RenderTemplate(w, r, "index/home", nil) 10 | }) 11 | 12 | mux.Handle( 13 | "/assets/", 14 | http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))), 15 | ) 16 | 17 | http.ListenAndServe(":3000", mux) 18 | } 19 | -------------------------------------------------------------------------------- /chapter4/2_first_template/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "net/http" 4 | 5 | func main() { 6 | mux := http.NewServeMux() 7 | 8 | mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 9 | RenderTemplate(w, r, "index/home", nil) 10 | }) 11 | 12 | mux.Handle( 13 | "/assets/", 14 | http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))), 15 | ) 16 | 17 | http.ListenAndServe(":3000", mux) 18 | } 19 | -------------------------------------------------------------------------------- /ig/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter8/0_base/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter10/0_base/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter10/2_godeps/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter8/0_base/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/0_base/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter10/0_base/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter10/examples/2_exporting_values/foo/foo.go: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | import "fmt" 4 | 5 | type Bar struct { 6 | Visible bool 7 | hidden bool 8 | } 9 | 10 | func NewBar() Bar { 11 | return Bar{ 12 | Visible: true, 13 | hidden: true, 14 | } 15 | } 16 | 17 | func (bar Bar) String() string { 18 | return bar.status() 19 | } 20 | func (bar Bar) status() string { 21 | return fmt.Sprintf("Visible is %T and hidden is %T", bar.Visible, bar.hidden) 22 | } 23 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter9/0_base/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/examples/1_addition/addition_test.go: -------------------------------------------------------------------------------- 1 | // addition_test.go 2 | package main 3 | 4 | import "testing" 5 | 6 | func TestOnePlusOne(t *testing.T) { 7 | onePlusOne := 1 + 1 8 | if onePlusOne != 2 { 9 | t.Error("Expected 1 + 1 to equal 2, but got", onePlusOne) 10 | } 11 | } 12 | 13 | func TestTwoPlusTwo(t *testing.T) { 14 | twoPlusTwo := 2 + 2 15 | if twoPlusTwo != 4 { 16 | t.Error("Expected 2 + 2 to equal 4, but got", twoPlusTwo) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter10/2_godeps/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/handle_index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleHome(w http.ResponseWriter, r *http.Request, params httprouter.Params) { 10 | // Display Home Page 11 | images, err := globalImageStore.FindAll(0) 12 | if err != nil { 13 | panic(err) 14 | } 15 | RenderTemplate(w, r, "index/home", map[string]interface{}{ 16 | "Images": images, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /chapter4/3_layouts/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | 14 | {{end}} 15 | -------------------------------------------------------------------------------- /chapter6/4_template_data/data/sessions.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sessions": { 3 | "sess_GBEX1Qx0NXmSgXL1nPDg": { 4 | "Id": "sess_GBEX1Qx0NXmSgXL1nPDg", 5 | "UserId": "usr_CydtIC9KUZG0Cbjx", 6 | "Expiry": "2014-10-16T21:52:36.144147885+13:00" 7 | }, 8 | "sess_UZA8Sihz7VQ7isxoedFE": { 9 | "Id": "sess_UZA8Sihz7VQ7isxoedFE", 10 | "UserId": "usr_Bw5ctWmCcko8fzIS", 11 | "Expiry": "2014-11-12T10:51:49.412724459+13:00" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /chapter8/2_display_resized/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter4/4_httprouter/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | 14 | {{end}} 15 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/templates/images/index.html: -------------------------------------------------------------------------------- 1 | {{define "images/index"}} 2 |
3 | {{if .Images}} 4 | {{range .Images}} 5 |
6 | 7 | 8 | 9 |
10 | {{end}} 11 | {{else}} 12 |

No Images Yet

13 | Why not upload one? 14 | {{end}} 15 |
16 | {{end}} 17 | -------------------------------------------------------------------------------- /chapter1/starwars.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | starWarsYears := map[string]int{ 7 | "A New Hope": 1977, 8 | "The Empire Strikes Back": 1980, 9 | "Return of the Jedi": 1983, 10 | "Attack of the Clones": 2002, 11 | "Revenge of the Sith": 2005, 12 | } 13 | starWarsYears["The Force Awakens"] = 2015 14 | 15 | for title, year := range starWarsYears { 16 | fmt.Println(title, "was released in", year) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/user_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func TestNewUserNoUsername(t *testing.T) { 6 | _, err := NewUser("", "user@example.com", "password") 7 | if err != errNoUsername { 8 | t.Error("Expected err to be errNoUsername") 9 | } 10 | } 11 | 12 | func TestNewUserNoPassword(t *testing.T) { 13 | _, err := NewUser("user", "user@example.com", "") 14 | if err != errNoPassword { 15 | t.Error("Expected err to be errNoUsername") 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /chapter9/examples/2_wrapper_functions/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | str := "How do I test this message is being written?" 10 | loc := "test.txt" 11 | err := WriteStuff(str, loc) 12 | if err != nil { 13 | panic(err) 14 | } 15 | } 16 | 17 | func WriteStuff(str, loc string) error { 18 | err := writeFile(loc, []byte(str), os.ModeAppend) 19 | if err != nil { 20 | return err 21 | } 22 | return nil 23 | } 24 | 25 | var writeFile = ioutil.WriteFile 26 | -------------------------------------------------------------------------------- /ig/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func init() { 12 | db, err := NewMySQLDB("root:root@tcp(127.0.0.1:3306)/gophr") 13 | if err != nil { 14 | panic(err) 15 | } 16 | globalMySQLDB = db 17 | } 18 | 19 | func NewMySQLDB(dsn string) (*sql.DB, error) { 20 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | return db, db.Ping() 26 | } 27 | -------------------------------------------------------------------------------- /ig/data/users.json: -------------------------------------------------------------------------------- 1 | { 2 | "Users": { 3 | "usr_Mp8ry7c6D4dUuPCd": { 4 | "ID": "usr_Mp8ry7c6D4dUuPCd", 5 | "Email": "mal2@mal.co.nz", 6 | "HashedPassword": "$2a$10$YC/GQMgxWiomR2Yi1kgZvu3hK7AMjfev.47Xd95r1UVGVFKpF2NX6", 7 | "Username": "NotMal" 8 | }, 9 | "usr_UvfFNCUI2pp3fLIh": { 10 | "ID": "usr_UvfFNCUI2pp3fLIh", 11 | "Email": "mal@mal.co.nz", 12 | "HashedPassword": "$2a$10$hd49NkCFrkoI2sjd9o28S.lvzTG764dXZQYFRe4zcsOozRvfih5C.", 13 | "Username": "mal" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /chapter7/1_mysql/mysql.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | var globalMySQLDB *sql.DB 10 | 11 | func init() { 12 | db, err := NewMySQLDB("root:root@tcp(127.0.0.1:3306)/gophr") 13 | if err != nil { 14 | panic(err) 15 | } 16 | globalMySQLDB = db 17 | } 18 | 19 | func NewMySQLDB(dsn string) (*sql.DB, error) { 20 | db, err := sql.Open("mysql", dsn+"?parseTime=true") 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | return db, db.Ping() 26 | } 27 | -------------------------------------------------------------------------------- /chapter5/2_registration/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | ) 13 | 14 | func IsValidationError(err error) bool { 15 | _, ok := err.(ValidationError) 16 | return ok 17 | } 18 | -------------------------------------------------------------------------------- /ig/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.ID .CurrentUser.ID}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter5/0_base/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 18 | {{ yield }} 19 | 20 | 21 | -------------------------------------------------------------------------------- /chapter5/1_router/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 18 | {{ yield }} 19 | 20 | 21 | -------------------------------------------------------------------------------- /chapter6/0_base/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 18 | {{ yield }} 19 | 20 | 21 | -------------------------------------------------------------------------------- /chapter5/3_user_store/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 18 | {{ yield }} 19 | 20 | 21 | -------------------------------------------------------------------------------- /chapter6/1_new_session/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 18 | {{ yield }} 19 | 20 | 21 | -------------------------------------------------------------------------------- /chapter8/0_base/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter9/0_base/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter10/0_base/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter10/2_godeps/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter5/2_registration/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 18 | {{ yield }} 19 | 20 | 21 | -------------------------------------------------------------------------------- /chapter6/2_session_store/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 18 | {{ yield }} 19 | 20 | 21 | -------------------------------------------------------------------------------- /chapter6/3_require_login/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 18 | {{ yield }} 19 | 20 | 21 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/templates/users/show.html: -------------------------------------------------------------------------------- 1 | {{define "users/show"}} 2 |
3 |
4 |
5 | 6 | {{.User.Username}} 7 | 8 |
9 |

10 | {{.User.Username}} 11 | {{if eq .User.Id .CurrentUser.Id}} 12 | (this is you) 13 | {{end}} 14 |

15 |
16 |
17 |
18 |
19 | {{template "images/index" .}} 20 | {{end}} 21 | -------------------------------------------------------------------------------- /chapter10/2_godeps/Godeps/_workspace/src/github.com/go-sql-driver/mysql/appengine.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | // +build appengine 10 | 11 | package mysql 12 | 13 | import ( 14 | "appengine/cloudsql" 15 | ) 16 | 17 | func init() { 18 | RegisterDial("cloudsql", cloudsql.Dial) 19 | } 20 | -------------------------------------------------------------------------------- /chapter4/2_first_template/templates/index/home.html: -------------------------------------------------------------------------------- 1 | {{define "index/home"}} 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | {{end}} 22 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/data/sessions.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sessions": { 3 | "sess_GBEX1Qx0NXmSgXL1nPDg": { 4 | "Id": "sess_GBEX1Qx0NXmSgXL1nPDg", 5 | "UserId": "usr_CydtIC9KUZG0Cbjx", 6 | "Expiry": "2014-10-16T21:52:36.144147885+13:00" 7 | }, 8 | "sess_khdIzL8FVrDg9eB1Fip1": { 9 | "Id": "sess_khdIzL8FVrDg9eB1Fip1", 10 | "UserId": "usr_ZRtM7bsqwge7ooxU", 11 | "Expiry": "2014-11-12T22:13:30.730961965+13:00" 12 | }, 13 | "sess_rpCFwRBPmdfiP0NJNm4X": { 14 | "Id": "sess_rpCFwRBPmdfiP0NJNm4X", 15 | "UserId": "", 16 | "Expiry": "2014-11-12T21:42:33.717113688+13:00" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /chapter8/0_base/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /ig/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | 20 | -------------------------------------------------------------------------------- /chapter10/0_base/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/data/sessions.json: -------------------------------------------------------------------------------- 1 | { 2 | "Sessions": { 3 | "sess_5JZPid0vn0m72Q0H3Ghh": { 4 | "Id": "sess_5JZPid0vn0m72Q0H3Ghh", 5 | "UserId": "usr_ZRtM7bsqwge7ooxU", 6 | "Expiry": "2014-11-12T21:42:37.07205867+13:00" 7 | }, 8 | "sess_GBEX1Qx0NXmSgXL1nPDg": { 9 | "Id": "sess_GBEX1Qx0NXmSgXL1nPDg", 10 | "UserId": "usr_CydtIC9KUZG0Cbjx", 11 | "Expiry": "2014-10-16T21:52:36.144147885+13:00" 12 | }, 13 | "sess_rpCFwRBPmdfiP0NJNm4X": { 14 | "Id": "sess_rpCFwRBPmdfiP0NJNm4X", 15 | "UserId": "", 16 | "Expiry": "2014-11-12T21:42:33.717113688+13:00" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /chapter9/0_base/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter10/2_godeps/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/templates/images/show.html: -------------------------------------------------------------------------------- 1 | {{define "images/show"}} 2 |
3 |
4 | {{.Image.Description}} 5 |
6 |
7 |
8 | 9 | {{.User.Username}} 10 | 11 |
12 |

{{.User.Username}}

13 |

{{.Image.Description}}

14 |
15 |
16 |
17 |
18 | {{end}} 19 | -------------------------------------------------------------------------------- /chapter3/3-time-handler/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | // UptimeHandler writes the number of seconds since starting to the response. 10 | type UptimeHandler struct { 11 | Started time.Time 12 | } 13 | 14 | func NewUptimeHandler() UptimeHandler { 15 | return UptimeHandler{ Started: time.Now() } 16 | } 17 | 18 | func (h UptimeHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { 19 | fmt.Fprintf( 20 | w, 21 | fmt.Sprintf("Current Uptime: %s", time.Since(h.Started)), 22 | ) 23 | } 24 | 25 | func main() { 26 | http.Handle("/", NewUptimeHandler()) 27 | http.ListenAndServe(":3000", nil) 28 | } 29 | -------------------------------------------------------------------------------- /chapter3/8-unknown-json-input/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | func FooJSON(input string) { 9 | data := map[string]interface{}{} 10 | err := json.Unmarshal([]byte(input), &data) 11 | if err != nil { 12 | panic(err) 13 | } 14 | foo, _ := data["foo"] 15 | switch foo.(type) { 16 | case float64: 17 | fmt.Printf("Float %f\n", foo) 18 | case string: 19 | fmt.Printf("String %s\n", foo) 20 | default: 21 | fmt.Printf("Something else\n") 22 | } 23 | } 24 | func main() { 25 | FooJSON(`{ 26 | "foo": 123 27 | }`) 28 | FooJSON(`{ 29 | "foo": "bar" 30 | }`) 31 | FooJSON(`{ 32 | "foo": [] 33 | }`) 34 | } 35 | -------------------------------------------------------------------------------- /chapter4/2_first_template/template.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "html/template" 6 | "net/http" 7 | ) 8 | 9 | var templates = template.Must(template.New("t").ParseGlob("templates/**/*.html")) 10 | 11 | var errorTemplate = ` 12 | 13 | 14 |

Error rendering template %s

15 |

%s

16 | 17 | 18 | ` 19 | 20 | func RenderTemplate(w http.ResponseWriter, request *http.Request, name string, data interface{}) { 21 | err := templates.ExecuteTemplate(w, name, data) 22 | if err != nil { 23 | http.Error( 24 | w, 25 | fmt.Sprintf(errorTemplate, name, err), 26 | http.StatusInternalServerError, 27 | ) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /chapter3/5-html-templates/funcs/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "text/template" 6 | ) 7 | 8 | func Multiply(a, b float64) float64 { 9 | return a * b 10 | } 11 | 12 | func main() { 13 | tmpl := template.New("Foo") 14 | tmpl.Funcs(template.FuncMap{"multiply": Multiply}) 15 | 16 | tmpl, err = tmpl.Parse( 17 | "Price: ${{ multiply .Price .Quantity | printf \"%.2f\"}}\n", 18 | ) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | type Product struct { 24 | Price float64 25 | Quantity float64 26 | } 27 | err = tmpl.Execute(os.Stdout, Product{ 28 | Price: 12.3, 29 | Quantity: 2, 30 | }) 31 | if err != nil { 32 | panic(err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /chapter5/1_router/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func main() { 11 | router := NewRouter() 12 | 13 | router.Handle("GET", "/", HandleHome) 14 | 15 | router.ServeFiles( 16 | "/assets/*filepath", 17 | http.Dir("assets/"), 18 | ) 19 | 20 | middleware := Middleware{} 21 | middleware.Add(router) 22 | log.Fatal(http.ListenAndServe(":3000", middleware)) 23 | } 24 | 25 | // Creates a new router 26 | func NewRouter() *httprouter.Router { 27 | router := httprouter.New() 28 | router.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) 29 | return router 30 | } 31 | -------------------------------------------------------------------------------- /chapter6/0_base/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errUsernameExists = ValidationError(errors.New("That username is taken")) 13 | errEmailExists = ValidationError(errors.New("That email address has an account")) 14 | ) 15 | 16 | func IsValidationError(err error) bool { 17 | _, ok := err.(ValidationError) 18 | return ok 19 | } 20 | -------------------------------------------------------------------------------- /chapter5/3_user_store/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errUsernameExists = ValidationError(errors.New("That username is taken")) 13 | errEmailExists = ValidationError(errors.New("That email address has an account")) 14 | ) 15 | 16 | func IsValidationError(err error) bool { 17 | _, ok := err.(ValidationError) 18 | return ok 19 | } 20 | -------------------------------------------------------------------------------- /chapter6/1_new_session/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errUsernameExists = ValidationError(errors.New("That username is taken")) 13 | errEmailExists = ValidationError(errors.New("That email address has an account")) 14 | ) 15 | 16 | func IsValidationError(err error) bool { 17 | _, ok := err.(ValidationError) 18 | return ok 19 | } 20 | -------------------------------------------------------------------------------- /chapter6/2_session_store/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errUsernameExists = ValidationError(errors.New("That username is taken")) 13 | errEmailExists = ValidationError(errors.New("That email address has an account")) 14 | ) 15 | 16 | func IsValidationError(err error) bool { 17 | _, ok := err.(ValidationError) 18 | return ok 19 | } 20 | -------------------------------------------------------------------------------- /chapter6/3_require_login/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errUsernameExists = ValidationError(errors.New("That username is taken")) 13 | errEmailExists = ValidationError(errors.New("That email address has an account")) 14 | ) 15 | 16 | func IsValidationError(err error) bool { 17 | _, ok := err.(ValidationError) 18 | return ok 19 | } 20 | -------------------------------------------------------------------------------- /chapter6/4_template_data/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errUsernameExists = ValidationError(errors.New("That username is taken")) 13 | errEmailExists = ValidationError(errors.New("That email address has an account")) 14 | ) 15 | 16 | func IsValidationError(err error) bool { 17 | _, ok := err.(ValidationError) 18 | return ok 19 | } 20 | -------------------------------------------------------------------------------- /chapter10/2_godeps/Godeps/_workspace/src/github.com/go-sql-driver/mysql/result.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlResult struct { 12 | affectedRows int64 13 | insertId int64 14 | } 15 | 16 | func (res *mysqlResult) LastInsertId() (int64, error) { 17 | return res.insertId, nil 18 | } 19 | 20 | func (res *mysqlResult) RowsAffected() (int64, error) { 21 | return res.affectedRows, nil 22 | } 23 | -------------------------------------------------------------------------------- /chapter6/0_base/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func main() { 11 | router := NewRouter() 12 | 13 | router.Handle("GET", "/", HandleHome) 14 | router.Handle("GET", "/register", HandleUserNew) 15 | router.Handle("POST", "/register", HandleUserCreate) 16 | 17 | router.ServeFiles( 18 | "/assets/*filepath", 19 | http.Dir("assets/"), 20 | ) 21 | 22 | middleware := Middleware{} 23 | middleware.Add(router) 24 | log.Fatal(http.ListenAndServe(":3000", middleware)) 25 | } 26 | 27 | // Creates a new router 28 | func NewRouter() *httprouter.Router { 29 | router := httprouter.New() 30 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 31 | return router 32 | } 33 | -------------------------------------------------------------------------------- /chapter5/2_registration/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func main() { 11 | router := NewRouter() 12 | 13 | router.Handle("GET", "/", HandleHome) 14 | router.Handle("GET", "/register", HandleUserNew) 15 | router.Handle("POST", "/register", HandleUserCreate) 16 | 17 | router.ServeFiles( 18 | "/assets/*filepath", 19 | http.Dir("assets/"), 20 | ) 21 | 22 | middleware := Middleware{} 23 | middleware.Add(router) 24 | log.Fatal(http.ListenAndServe(":3000", middleware)) 25 | } 26 | 27 | // Creates a new router 28 | func NewRouter() *httprouter.Router { 29 | router := httprouter.New() 30 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 31 | return router 32 | } 33 | -------------------------------------------------------------------------------- /chapter5/3_user_store/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func main() { 11 | router := NewRouter() 12 | 13 | router.Handle("GET", "/", HandleHome) 14 | router.Handle("GET", "/register", HandleUserNew) 15 | router.Handle("POST", "/register", HandleUserCreate) 16 | 17 | router.ServeFiles( 18 | "/assets/*filepath", 19 | http.Dir("assets/"), 20 | ) 21 | 22 | middleware := Middleware{} 23 | middleware.Add(router) 24 | log.Fatal(http.ListenAndServe(":3000", middleware)) 25 | } 26 | 27 | // Creates a new router 28 | func NewRouter() *httprouter.Router { 29 | router := httprouter.New() 30 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 31 | return router 32 | } 33 | -------------------------------------------------------------------------------- /chapter6/1_new_session/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func main() { 11 | router := NewRouter() 12 | 13 | router.Handle("GET", "/", HandleHome) 14 | router.Handle("GET", "/register", HandleUserNew) 15 | router.Handle("POST", "/register", HandleUserCreate) 16 | 17 | router.ServeFiles( 18 | "/assets/*filepath", 19 | http.Dir("assets/"), 20 | ) 21 | 22 | middleware := Middleware{} 23 | middleware.Add(router) 24 | log.Fatal(http.ListenAndServe(":3000", middleware)) 25 | } 26 | 27 | // Creates a new router 28 | func NewRouter() *httprouter.Router { 29 | router := httprouter.New() 30 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 31 | return router 32 | } 33 | -------------------------------------------------------------------------------- /chapter6/2_session_store/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func main() { 11 | router := NewRouter() 12 | 13 | router.Handle("GET", "/", HandleHome) 14 | router.Handle("GET", "/register", HandleUserNew) 15 | router.Handle("POST", "/register", HandleUserCreate) 16 | 17 | router.ServeFiles( 18 | "/assets/*filepath", 19 | http.Dir("assets/"), 20 | ) 21 | 22 | middleware := Middleware{} 23 | middleware.Add(router) 24 | log.Fatal(http.ListenAndServe(":3000", middleware)) 25 | } 26 | 27 | // Creates a new router 28 | func NewRouter() *httprouter.Router { 29 | router := httprouter.New() 30 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 31 | return router 32 | } 33 | -------------------------------------------------------------------------------- /chapter6/3_require_login/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func main() { 11 | router := NewRouter() 12 | 13 | router.Handle("GET", "/", HandleHome) 14 | router.Handle("GET", "/register", HandleUserNew) 15 | router.Handle("POST", "/register", HandleUserCreate) 16 | 17 | router.ServeFiles( 18 | "/assets/*filepath", 19 | http.Dir("assets/"), 20 | ) 21 | 22 | middleware := Middleware{} 23 | middleware.Add(router) 24 | log.Fatal(http.ListenAndServe(":3000", middleware)) 25 | } 26 | 27 | // Creates a new router 28 | func NewRouter() *httprouter.Router { 29 | router := httprouter.New() 30 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 31 | return router 32 | } 33 | -------------------------------------------------------------------------------- /chapter6/4_template_data/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/julienschmidt/httprouter" 8 | ) 9 | 10 | func main() { 11 | router := NewRouter() 12 | 13 | router.Handle("GET", "/", HandleHome) 14 | router.Handle("GET", "/register", HandleUserNew) 15 | router.Handle("POST", "/register", HandleUserCreate) 16 | 17 | router.ServeFiles( 18 | "/assets/*filepath", 19 | http.Dir("assets/"), 20 | ) 21 | 22 | middleware := Middleware{} 23 | middleware.Add(router) 24 | log.Fatal(http.ListenAndServe(":3000", middleware)) 25 | } 26 | 27 | // Creates a new router 28 | func NewRouter() *httprouter.Router { 29 | router := httprouter.New() 30 | router.NotFound = func(http.ResponseWriter, *http.Request) {} 31 | return router 32 | } 33 | -------------------------------------------------------------------------------- /chapter6/1_new_session/session.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | type Session struct { 9 | ID string 10 | UserID string 11 | Expiry time.Time 12 | } 13 | 14 | const ( 15 | // Keep users logged in for 3 days 16 | sessionLength = 24 * 3 * time.Hour 17 | sessionCookieName = "GophrSession" 18 | sessionIDLength = 20 19 | ) 20 | 21 | func NewSession(w http.ResponseWriter) *Session { 22 | expiry := time.Now().Add(sessionLength) 23 | 24 | session := &Session{ 25 | ID: GenerateID("sess", sessionIDLength), 26 | Expiry: expiry, 27 | } 28 | 29 | cookie := http.Cookie{ 30 | Name: sessionCookieName, 31 | Value: session.ID, 32 | Expires: session.Expiry, 33 | } 34 | 35 | http.SetCookie(w, &cookie) 36 | return session 37 | } 38 | -------------------------------------------------------------------------------- /chapter6/2_session_store/session.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | type Session struct { 9 | ID string 10 | UserID string 11 | Expiry time.Time 12 | } 13 | 14 | const ( 15 | // Keep users logged in for 3 days 16 | sessionLength = 24 * 3 * time.Hour 17 | sessionCookieName = "GophrSession" 18 | sessionIDLength = 20 19 | ) 20 | 21 | func NewSession(w http.ResponseWriter) *Session { 22 | expiry := time.Now().Add(sessionLength) 23 | 24 | session := &Session{ 25 | ID: GenerateID("sess", sessionIDLength), 26 | Expiry: expiry, 27 | } 28 | 29 | cookie := http.Cookie{ 30 | Name: sessionCookieName, 31 | Value: session.ID, 32 | Expires: session.Expiry, 33 | } 34 | 35 | http.SetCookie(w, &cookie) 36 | return session 37 | } 38 | -------------------------------------------------------------------------------- /chapter5/2_registration/handle_user.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleUserNew(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 10 | RenderTemplate(w, r, "users/new", nil) 11 | } 12 | 13 | func HandleUserCreate(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 14 | user, err := NewUser( 15 | r.FormValue("username"), 16 | r.FormValue("email"), 17 | r.FormValue("password"), 18 | ) 19 | 20 | if err != nil { 21 | if IsValidationError(err) { 22 | RenderTemplate(w, r, "users/new", map[string]interface{}{ 23 | "Error": err.Error(), 24 | "User": user, 25 | }) 26 | return 27 | } 28 | panic(err) 29 | } 30 | 31 | http.Redirect(w, r, "/?flash=User+created", http.StatusFound) 32 | } 33 | -------------------------------------------------------------------------------- /ig/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter10/0_base/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter7/0_base/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter7/1_mysql/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter8/0_base/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter9/0_base/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /ig/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter10/2_godeps/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter3/7-unmarshaling-json/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | ) 8 | 9 | func main() { 10 | type Config struct { 11 | Name string `json:"SiteName"` 12 | URL string `json:"SiteUrl"` 13 | Database struct { 14 | Name string 15 | Host string 16 | Port int 17 | Username string 18 | Password string 19 | } 20 | } 21 | conf := Config{} 22 | data, err := ioutil.ReadFile("config.json") 23 | if err != nil { 24 | panic(err) 25 | } 26 | err = json.Unmarshal(data, &conf) 27 | if err != nil { 28 | panic(err) 29 | } 30 | fmt.Printf("Site: %s (%s)\n", conf.Name, conf.URL) 31 | db := conf.Database 32 | fmt.Printf( 33 | "DB: mysql://%s:%s@%s:%d/%s\n", 34 | db.Username, 35 | db.Password, 36 | db.Host, 37 | db.Port, 38 | db.Name, 39 | ) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter10/0_base/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter6/0_base/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter7/0_base/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter7/1_mysql/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter7/3_uploading_images/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter8/0_base/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter9/0_base/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter10/2_godeps/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter5/3_user_store/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/templates/sessions/new.html: -------------------------------------------------------------------------------- 1 | {{define "sessions/new"}} 2 |
3 |
4 |

Sign In

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 |
23 |
24 | {{end}} 25 | -------------------------------------------------------------------------------- /chapter5/2_registration/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter6/1_new_session/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter6/2_session_store/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter6/3_require_login/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter6/4_template_data/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter7/3_uploading_images/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/id.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | // Source String used when generating a random identifier. 9 | const idSource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 10 | 11 | // Save the length in a constant so we don't look it up each time. 12 | const idSourceLen = byte(len(idSource)) 13 | 14 | // GenerateID creates a prefixed random identifier. 15 | func GenerateID(prefix string, length int) string { 16 | // Create an array with the correct capacity 17 | id := make([]byte, length) 18 | // Fill our array with random numbers 19 | rand.Read(id) 20 | 21 | // Replace each random number with an alphanumeric value 22 | for i, b := range id { 23 | id[i] = idSource[b%idSourceLen] 24 | } 25 | 26 | // Return the formatted id 27 | return fmt.Sprintf("%s_%s", prefix, string(id)) 28 | } 29 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errUsernameExists = ValidationError(errors.New("That username is taken")) 13 | errEmailExists = ValidationError(errors.New("That email address has an account")) 14 | errCredentialsIncorrect = ValidationError(errors.New("We couldn’t find a user with the supplied username and password combination")) 15 | ) 16 | 17 | func IsValidationError(err error) bool { 18 | _, ok := err.(ValidationError) 19 | return ok 20 | } 21 | -------------------------------------------------------------------------------- /chapter10/0_base/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter6/0_base/handle_user.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleUserNew(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 10 | RenderTemplate(w, r, "users/new", nil) 11 | } 12 | 13 | func HandleUserCreate(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 14 | user, err := NewUser( 15 | r.FormValue("username"), 16 | r.FormValue("email"), 17 | r.FormValue("password"), 18 | ) 19 | 20 | if err != nil { 21 | if IsValidationError(err) { 22 | RenderTemplate(w, r, "users/new", map[string]interface{}{ 23 | "Error": err.Error(), 24 | "User": user, 25 | }) 26 | return 27 | } 28 | panic(err) 29 | return 30 | } 31 | 32 | err = globalUserStore.Save(user) 33 | if err != nil { 34 | panic(err) 35 | return 36 | } 37 | 38 | http.Redirect(w, r, "/?flash=User+created", http.StatusFound) 39 | } 40 | -------------------------------------------------------------------------------- /chapter6/0_base/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter7/0_base/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter7/1_mysql/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter8/0_base/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter9/0_base/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter10/2_godeps/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter5/3_user_store/handle_user.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | ) 8 | 9 | func HandleUserNew(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 10 | RenderTemplate(w, r, "users/new", nil) 11 | } 12 | 13 | func HandleUserCreate(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { 14 | user, err := NewUser( 15 | r.FormValue("username"), 16 | r.FormValue("email"), 17 | r.FormValue("password"), 18 | ) 19 | 20 | if err != nil { 21 | if IsValidationError(err) { 22 | RenderTemplate(w, r, "users/new", map[string]interface{}{ 23 | "Error": err.Error(), 24 | "User": user, 25 | }) 26 | return 27 | } 28 | panic(err) 29 | return 30 | } 31 | 32 | err = globalUserStore.Save(user) 33 | if err != nil { 34 | panic(err) 35 | return 36 | } 37 | 38 | http.Redirect(w, r, "/?flash=User+created", http.StatusFound) 39 | } 40 | -------------------------------------------------------------------------------- /chapter5/3_user_store/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter6/1_new_session/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter10/2_godeps/Godeps/_workspace/src/github.com/go-sql-driver/mysql/transaction.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlTx struct { 12 | mc *mysqlConn 13 | } 14 | 15 | func (tx *mysqlTx) Commit() (err error) { 16 | if tx.mc == nil || tx.mc.netConn == nil { 17 | return ErrInvalidConn 18 | } 19 | err = tx.mc.exec("COMMIT") 20 | tx.mc = nil 21 | return 22 | } 23 | 24 | func (tx *mysqlTx) Rollback() (err error) { 25 | if tx.mc == nil || tx.mc.netConn == nil { 26 | return ErrInvalidConn 27 | } 28 | err = tx.mc.exec("ROLLBACK") 29 | tx.mc = nil 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /chapter5/2_registration/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter6/2_session_store/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter6/3_require_login/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter6/4_template_data/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter7/3_uploading_images/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter8/1_image_resizing/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter8/2_display_resized/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter9/2_mock_interface/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter7/4_displaying_images/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /chapter9/1_simple_input_tests/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |

Sign Up

4 | {{if .Error}} 5 |

6 | {{.Error}} 7 |

8 | {{end}} 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 | {{end}} 26 | -------------------------------------------------------------------------------- /ig/templates/users/new.html: -------------------------------------------------------------------------------- 1 | {{define "users/new"}} 2 |
3 |
4 |

Sign Up

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 | 24 |
25 |
26 |
27 | {{end}} 28 | -------------------------------------------------------------------------------- /chapter7/0_base/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errPasswordIncorrect = ValidationError(errors.New("Password did not match")) 13 | errUsernameExists = ValidationError(errors.New("That username is taken")) 14 | errEmailExists = ValidationError(errors.New("That email address has an account")) 15 | errCredentialsIncorrect = ValidationError(errors.New("We couldn’t find a user with the supplied username and password combination")) 16 | ) 17 | 18 | func IsValidationError(err error) bool { 19 | _, ok := err.(ValidationError) 20 | return ok 21 | } 22 | -------------------------------------------------------------------------------- /chapter7/1_mysql/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errPasswordIncorrect = ValidationError(errors.New("Password did not match")) 13 | errUsernameExists = ValidationError(errors.New("That username is taken")) 14 | errEmailExists = ValidationError(errors.New("That email address has an account")) 15 | errCredentialsIncorrect = ValidationError(errors.New("We couldn’t find a user with the supplied username and password combination")) 16 | ) 17 | 18 | func IsValidationError(err error) bool { 19 | _, ok := err.(ValidationError) 20 | return ok 21 | } 22 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errPasswordIncorrect = ValidationError(errors.New("Password did not match")) 13 | errUsernameExists = ValidationError(errors.New("That username is taken")) 14 | errEmailExists = ValidationError(errors.New("That email address has an account")) 15 | errCredentialsIncorrect = ValidationError(errors.New("We couldn’t find a user with the supplied username and password combination")) 16 | ) 17 | 18 | func IsValidationError(err error) bool { 19 | _, ok := err.(ValidationError) 20 | return ok 21 | } 22 | -------------------------------------------------------------------------------- /chapter7/0_base/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 24 |
25 | {{if .Flash}} 26 |
27 | {{.Flash}} 28 |
29 | {{end}} 30 | {{ yield }} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /chapter10/2_godeps/Godeps/_workspace/src/golang.org/x/image/tiff/buffer_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package tiff 6 | 7 | import ( 8 | "io" 9 | "strings" 10 | "testing" 11 | ) 12 | 13 | var readAtTests = []struct { 14 | n int 15 | off int64 16 | s string 17 | err error 18 | }{ 19 | {2, 0, "ab", nil}, 20 | {6, 0, "abcdef", nil}, 21 | {3, 3, "def", nil}, 22 | {3, 5, "f", io.EOF}, 23 | {3, 6, "", io.EOF}, 24 | } 25 | 26 | func TestReadAt(t *testing.T) { 27 | r := newReaderAt(strings.NewReader("abcdef")) 28 | b := make([]byte, 10) 29 | for _, test := range readAtTests { 30 | n, err := r.ReadAt(b[:test.n], test.off) 31 | s := string(b[:n]) 32 | if s != test.s || err != test.err { 33 | t.Errorf("buffer.ReadAt(<%v bytes>, %v): got %v, %q; want %v, %q", test.n, test.off, err, s, test.err, test.s) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /chapter6/6_edit_user/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 24 |
25 | {{if .Flash}} 26 |
27 | {{.Flash}} 28 |
29 | {{end}} 30 | {{ yield }} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /chapter7/1_mysql/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 24 |
25 | {{if .Flash}} 26 |
27 | {{.Flash}} 28 |
29 | {{end}} 30 | {{ yield }} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "errors" 4 | 5 | type ValidationError error 6 | 7 | var ( 8 | errNoUsername = ValidationError(errors.New("You must supply a username")) 9 | errNoEmail = ValidationError(errors.New("You must supply an email")) 10 | errNoPassword = ValidationError(errors.New("You must supply a password")) 11 | errPasswordTooShort = ValidationError(errors.New("Your password is too short")) 12 | errPasswordIncorrect = ValidationError(errors.New("Password did not match")) 13 | errUsernameExists = ValidationError(errors.New("That username is taken")) 14 | errEmailExists = ValidationError(errors.New("That email address has an account")) 15 | errCredentialsIncorrect = ValidationError(errors.New("We couldn’t find a user with the supplied username and password combination")) 16 | ) 17 | 18 | func IsValidationError(err error) bool { 19 | _, ok := err.(ValidationError) 20 | return ok 21 | } 22 | -------------------------------------------------------------------------------- /chapter6/4_template_data/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 24 |
25 | {{if .Flash}} 26 |
27 | {{.Flash}} 28 |
29 | {{end}} 30 | {{ yield }} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /chapter7/2_db_image_store/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 24 |
25 | {{if .Flash}} 26 |
27 | {{.Flash}} 28 |
29 | {{end}} 30 | {{ yield }} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /chapter6/5_signing_out_and_in/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 24 |
25 | {{if .Flash}} 26 |
27 | {{.Flash}} 28 |
29 | {{end}} 30 | {{ yield }} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /chapter10/0_base/image_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | ) 8 | 9 | func TestImageCreateFromURLInvalidStatusCode(t *testing.T) { 10 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 11 | w.WriteHeader(404) 12 | })) 13 | defer server.Close() 14 | 15 | image := Image{} 16 | err := image.CreateFromURL(server.URL) 17 | if err != errImageURLInvalid { 18 | t.Errorf("Expected errImageURLInvalid but got %s", err) 19 | } 20 | } 21 | 22 | func TestImageCreateFromURLInvalidContentType(t *testing.T) { 23 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 24 | w.WriteHeader(200) 25 | w.Header().Add("Content-Type", "text/html") 26 | })) 27 | defer server.Close() 28 | 29 | image := Image{} 30 | err := image.CreateFromURL(server.URL) 31 | if err != errInvalidImageType { 32 | t.Errorf("Expected errInvalidImageType but got %s", err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /chapter10/1_pkg_web/image_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | ) 8 | 9 | func TestImageCreateFromURLInvalidStatusCode(t *testing.T) { 10 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 11 | w.WriteHeader(404) 12 | })) 13 | defer server.Close() 14 | 15 | image := Image{} 16 | err := image.CreateFromURL(server.URL) 17 | if err != errImageURLInvalid { 18 | t.Errorf("Expected errImageURLInvalid but got %s", err) 19 | } 20 | } 21 | 22 | func TestImageCreateFromURLInvalidContentType(t *testing.T) { 23 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 24 | w.WriteHeader(200) 25 | w.Header().Add("Content-Type", "text/html") 26 | })) 27 | defer server.Close() 28 | 29 | image := Image{} 30 | err := image.CreateFromURL(server.URL) 31 | if err != errInvalidImageType { 32 | t.Errorf("Expected errInvalidImageType but got %s", err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /chapter10/2_godeps/image_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | ) 8 | 9 | func TestImageCreateFromURLInvalidStatusCode(t *testing.T) { 10 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 11 | w.WriteHeader(404) 12 | })) 13 | defer server.Close() 14 | 15 | image := Image{} 16 | err := image.CreateFromURL(server.URL) 17 | if err != errImageURLInvalid { 18 | t.Errorf("Expected errImageURLInvalid but got %s", err) 19 | } 20 | } 21 | 22 | func TestImageCreateFromURLInvalidContentType(t *testing.T) { 23 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 24 | w.WriteHeader(200) 25 | w.Header().Add("Content-Type", "text/html") 26 | })) 27 | defer server.Close() 28 | 29 | image := Image{} 30 | err := image.CreateFromURL(server.URL) 31 | if err != errInvalidImageType { 32 | t.Errorf("Expected errInvalidImageType but got %s", err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /chapter5/2_registration/user.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "code.google.com/p/go.crypto/bcrypt" 4 | 5 | type User struct { 6 | ID string 7 | Email string 8 | HashedPassword string 9 | Username string 10 | } 11 | 12 | const ( 13 | hashCost = 10 14 | passwordLength = 6 15 | userIDLength = 16 16 | ) 17 | 18 | func NewUser(username, email, password string) (User, error) { 19 | user := User{ 20 | Email: email, 21 | Username: username, 22 | } 23 | if username == "" { 24 | return user, errNoUsername 25 | } 26 | 27 | if email == "" { 28 | return user, errNoEmail 29 | } 30 | 31 | if password == "" { 32 | return user, errNoPassword 33 | } 34 | 35 | if len(password) < passwordLength { 36 | return user, errPasswordTooShort 37 | } 38 | hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), hashCost) 39 | 40 | user.HashedPassword = string(hashedPassword) 41 | user.ID = GenerateID("usr", userIDLength) 42 | return user, err 43 | } 44 | -------------------------------------------------------------------------------- /chapter9/3_http_testing/image_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | ) 8 | 9 | func TestImageCreateFromURLInvalidStatusCode(t *testing.T) { 10 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 11 | w.WriteHeader(404) 12 | })) 13 | defer server.Close() 14 | 15 | image := Image{} 16 | err := image.CreateFromURL(server.URL) 17 | if err != errImageURLInvalid { 18 | t.Errorf("Expected errImageURLInvalid but got %s", err) 19 | } 20 | } 21 | 22 | func TestImageCreateFromURLInvalidContentType(t *testing.T) { 23 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 24 | w.WriteHeader(200) 25 | w.Header().Add("Content-Type", "text/html") 26 | })) 27 | defer server.Close() 28 | 29 | image := Image{} 30 | err := image.CreateFromURL(server.URL) 31 | if err != errInvalidImageType { 32 | t.Errorf("Expected errInvalidImageType but got %s", err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /chapter9/4_benchmarking/image_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | ) 8 | 9 | func TestImageCreateFromURLInvalidStatusCode(t *testing.T) { 10 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 11 | w.WriteHeader(404) 12 | })) 13 | defer server.Close() 14 | 15 | image := Image{} 16 | err := image.CreateFromURL(server.URL) 17 | if err != errImageURLInvalid { 18 | t.Errorf("Expected errImageURLInvalid but got %s", err) 19 | } 20 | } 21 | 22 | func TestImageCreateFromURLInvalidContentType(t *testing.T) { 23 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 24 | w.WriteHeader(200) 25 | w.Header().Add("Content-Type", "text/html") 26 | })) 27 | defer server.Close() 28 | 29 | image := Image{} 30 | err := image.CreateFromURL(server.URL) 31 | if err != errInvalidImageType { 32 | t.Errorf("Expected errInvalidImageType but got %s", err) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ig/templates/images/new.html: -------------------------------------------------------------------------------- 1 | {{define "images/new"}} 2 |
3 |
4 |

Add An Image

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 | 24 |
25 |
26 |
27 | {{end}} 28 | -------------------------------------------------------------------------------- /chapter10/0_base/templates/images/new.html: -------------------------------------------------------------------------------- 1 | {{define "images/new"}} 2 |
3 |
4 |

Add An Image

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 | 24 |
25 |
26 |
27 | {{end}} 28 | -------------------------------------------------------------------------------- /chapter8/0_base/templates/images/new.html: -------------------------------------------------------------------------------- 1 | {{define "images/new"}} 2 |
3 |
4 |

Add An Image

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 | 24 |
25 |
26 |
27 | {{end}} 28 | -------------------------------------------------------------------------------- /chapter9/0_base/templates/images/new.html: -------------------------------------------------------------------------------- 1 | {{define "images/new"}} 2 |
3 |
4 |

Add An Image

5 | {{if .Error}} 6 |

7 | {{.Error}} 8 |

9 | {{end}} 10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 |
20 | 21 | 22 |
23 | 24 |
25 |
26 |
27 | {{end}} 28 | --------------------------------------------------------------------------------