master c294b087b96d cached
1809 files
4.4 MB
1.2M tokens
1472 symbols
1 requests
Download .txt
Showing preview only (4,804K chars total). Download the full file or copy to clipboard to get everything.
Repository: astaxie/build-web-application-with-golang
Branch: master
Commit: c294b087b96d
Files: 1809
Total size: 4.4 MB

Directory structure:
gitextract_hws5bolv/

├── LANGS.md
├── LICENSE.md
├── README.md
├── bn/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── preface.md
│   └── ref.md
├── de/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── preface.md
│   └── ref.md
├── en/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── build.go
│   ├── build.sh
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── eBook/
│   │   ├── 05.0.md
│   │   └── 05.0.md.orig
│   ├── images/
│   │   ├── 1.1.cmd.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.cmd.png~update the structure for gitbook
│   │   ├── 1.1.linux.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.linux.png~update the structure for gitbook
│   │   ├── 1.1.mac.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.mac.png~update the structure for gitbook
│   │   ├── 1.3.go.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.3.go.png~update the structure for gitbook
│   │   ├── 1.4.eclipse1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse1.png~update the structure for gitbook
│   │   ├── 1.4.eclipse2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse2.png~update the structure for gitbook
│   │   ├── 1.4.eclipse3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse3.png~update the structure for gitbook
│   │   ├── 1.4.eclipse4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse4.png~update the structure for gitbook
│   │   ├── 1.4.eclipse5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse5.png~update the structure for gitbook
│   │   ├── 1.4.eclipse6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse6.png~update the structure for gitbook
│   │   ├── 1.4.emacs.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.emacs.png~update the structure for gitbook
│   │   ├── 1.4.idea1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea1.png~update the structure for gitbook
│   │   ├── 1.4.idea2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea2.png~update the structure for gitbook
│   │   ├── 1.4.idea3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea3.png~update the structure for gitbook
│   │   ├── 1.4.idea4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea4.png~update the structure for gitbook
│   │   ├── 1.4.idea5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea5.png~update the structure for gitbook
│   │   ├── 1.4.liteide.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.liteide.png~update the structure for gitbook
│   │   ├── 1.4.sublime1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime1.png~update the structure for gitbook
│   │   ├── 1.4.sublime2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime2.png~update the structure for gitbook
│   │   ├── 1.4.sublime3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime3.png~update the structure for gitbook
│   │   ├── 1.4.sublime4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime4.png~update the structure for gitbook
│   │   ├── 1.4.vim.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.vim.png~update the structure for gitbook
│   │   ├── 13.1.gopath.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath.png~update the structure for gitbook
│   │   ├── 13.1.gopath2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath2.png~update the structure for gitbook
│   │   ├── 13.4.beego.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.4.beego.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap2.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap3.png~update the structure for gitbook
│   │   ├── 14.4.github.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github.png~update the structure for gitbook
│   │   ├── 14.4.github2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github2.png~update the structure for gitbook
│   │   ├── 14.4.github3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github3.png~update the structure for gitbook
│   │   ├── 14.6.pprof.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof.png~update the structure for gitbook
│   │   ├── 14.6.pprof2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof2.png~update the structure for gitbook
│   │   ├── 14.6.pprof3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof3.png~update the structure for gitbook
│   │   ├── 2.2.array.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.array.png~update the structure for gitbook
│   │   ├── 2.2.basic.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.basic.png~update the structure for gitbook
│   │   ├── 2.2.makenew.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.makenew.png~update the structure for gitbook
│   │   ├── 2.2.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice.png~update the structure for gitbook
│   │   ├── 2.2.slice2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice2.png~update the structure for gitbook
│   │   ├── 2.3.init.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.3.init.png~update the structure for gitbook
│   │   ├── 2.4.student_struct.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.4.student_struct.png~update the structure for gitbook
│   │   ├── 2.5.rect_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.rect_func_without_receiver.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_without_receiver.png~update the structure for gitbook
│   │   ├── 3.1.dns2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns2.png~update the structure for gitbook
│   │   ├── 3.1.dns_hierachy.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_hierachy.png~update the structure for gitbook
│   │   ├── 3.1.dns_inquery.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_inquery.png~update the structure for gitbook
│   │   ├── 3.1.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.http.png~update the structure for gitbook
│   │   ├── 3.1.httpPOST.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.httpPOST.png~update the structure for gitbook
│   │   ├── 3.1.response.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.response.png~update the structure for gitbook
│   │   ├── 3.1.web.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web.png~update the structure for gitbook
│   │   ├── 3.1.web2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web2.png~update the structure for gitbook
│   │   ├── 3.2.goweb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.2.goweb.png~update the structure for gitbook
│   │   ├── 3.3.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.http.png~update the structure for gitbook
│   │   ├── 3.3.illustrator.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.illustrator.png~update the structure for gitbook
│   │   ├── 4.1.login.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.login.png~update the structure for gitbook
│   │   ├── 4.1.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.slice.png~update the structure for gitbook
│   │   ├── 4.3.escape.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.3.escape.png~update the structure for gitbook
│   │   ├── 4.4.token.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.4.token.png~update the structure for gitbook
│   │   ├── 4.5.upload.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload.png~update the structure for gitbook
│   │   ├── 4.5.upload2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload2.png~update the structure for gitbook
│   │   ├── 5.6.mongodb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 5.6.mongodb.png~update the structure for gitbook
│   │   ├── 6.1.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie.png~update the structure for gitbook
│   │   ├── 6.1.cookie2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie2.png~update the structure for gitbook
│   │   ├── 6.1.session.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.session.png~update the structure for gitbook
│   │   ├── 6.4.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.cookie.png~update the structure for gitbook
│   │   ├── 6.4.hijack.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijack.png~update the structure for gitbook
│   │   ├── 6.4.hijacksuccess.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijacksuccess.png~update the structure for gitbook
│   │   ├── 6.4.setcookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.setcookie.png~update the structure for gitbook
│   │   ├── 7.4.template.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 7.4.template.png~update the structure for gitbook
│   │   ├── 8.1.socket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.1.socket.png~update the structure for gitbook
│   │   ├── 8.2.websocket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket.png~update the structure for gitbook
│   │   ├── 8.2.websocket2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket2.png~update the structure for gitbook
│   │   ├── 8.2.websocket3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket3.png~update the structure for gitbook
│   │   ├── 8.3.rest.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest.png~update the structure for gitbook
│   │   ├── 8.3.rest2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest2.png~update the structure for gitbook
│   │   ├── 8.3.rest3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest3.png~update the structure for gitbook
│   │   ├── 8.4.rpc.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.4.rpc.png~update the structure for gitbook
│   │   ├── 9.1.csrf.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 9.1.csrf.png~update the structure for gitbook
│   │   ├── cover.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── cover.png~update the structure for gitbook
│   │   ├── ebook.jpg~380a8ee74c41759d8189ad553423467994187253
│   │   ├── ebook.jpg~update the structure for gitbook
│   │   ├── navi1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi1.png~update the structure for gitbook
│   │   ├── navi10.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi10.png~update the structure for gitbook
│   │   ├── navi11.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi11.png~update the structure for gitbook
│   │   ├── navi12.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi12.png~update the structure for gitbook
│   │   ├── navi13.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi13.png~update the structure for gitbook
│   │   ├── navi14.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi14.png~update the structure for gitbook
│   │   ├── navi2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi2.png~update the structure for gitbook
│   │   ├── navi3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi3.png~update the structure for gitbook
│   │   ├── navi4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi4.png~update the structure for gitbook
│   │   ├── navi5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi5.png~update the structure for gitbook
│   │   ├── navi6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi6.png~update the structure for gitbook
│   │   ├── navi7.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi7.png~update the structure for gitbook
│   │   ├── navi8.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi8.png~update the structure for gitbook
│   │   ├── navi9.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi9.png~update the structure for gitbook
│   │   ├── polling.png~380a8ee74c41759d8189ad553423467994187253
│   │   └── polling.png~update the structure for gitbook
│   ├── preface.md
│   ├── ref.md
│   └── src/
│       └── 1.2/
│           ├── main.go
│           └── sqrt.go
├── es/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── README.md
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   └── ch.1.2/
│   │       │       └── main.go
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── preface.md
│   └── ref.md
├── fa/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── README.md
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── images/
│   │   ├── 1.1.cmd.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.cmd.png~update the structure for gitbook
│   │   ├── 1.1.linux.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.linux.png~update the structure for gitbook
│   │   ├── 1.1.mac.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.mac.png~update the structure for gitbook
│   │   ├── 1.3.go.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.3.go.png~update the structure for gitbook
│   │   ├── 1.4.eclipse1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse1.png~update the structure for gitbook
│   │   ├── 1.4.eclipse2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse2.png~update the structure for gitbook
│   │   ├── 1.4.eclipse3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse3.png~update the structure for gitbook
│   │   ├── 1.4.eclipse4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse4.png~update the structure for gitbook
│   │   ├── 1.4.eclipse5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse5.png~update the structure for gitbook
│   │   ├── 1.4.eclipse6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse6.png~update the structure for gitbook
│   │   ├── 1.4.emacs.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.emacs.png~update the structure for gitbook
│   │   ├── 1.4.idea1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea1.png~update the structure for gitbook
│   │   ├── 1.4.idea2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea2.png~update the structure for gitbook
│   │   ├── 1.4.idea3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea3.png~update the structure for gitbook
│   │   ├── 1.4.idea4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea4.png~update the structure for gitbook
│   │   ├── 1.4.idea5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea5.png~update the structure for gitbook
│   │   ├── 1.4.liteide.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.liteide.png~update the structure for gitbook
│   │   ├── 1.4.sublime1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime1.png~update the structure for gitbook
│   │   ├── 1.4.sublime2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime2.png~update the structure for gitbook
│   │   ├── 1.4.sublime3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime3.png~update the structure for gitbook
│   │   ├── 1.4.sublime4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime4.png~update the structure for gitbook
│   │   ├── 1.4.vim.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.vim.png~update the structure for gitbook
│   │   ├── 13.1.gopath.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath.png~update the structure for gitbook
│   │   ├── 13.1.gopath2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath2.png~update the structure for gitbook
│   │   ├── 13.4.beego.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.4.beego.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap2.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap3.png~update the structure for gitbook
│   │   ├── 14.4.github.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github.png~update the structure for gitbook
│   │   ├── 14.4.github2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github2.png~update the structure for gitbook
│   │   ├── 14.4.github3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github3.png~update the structure for gitbook
│   │   ├── 14.6.pprof.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof.png~update the structure for gitbook
│   │   ├── 14.6.pprof2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof2.png~update the structure for gitbook
│   │   ├── 14.6.pprof3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof3.png~update the structure for gitbook
│   │   ├── 2.2.array.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.array.png~update the structure for gitbook
│   │   ├── 2.2.basic.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.basic.png~update the structure for gitbook
│   │   ├── 2.2.makenew.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.makenew.png~update the structure for gitbook
│   │   ├── 2.2.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice.png~update the structure for gitbook
│   │   ├── 2.2.slice2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice2.png~update the structure for gitbook
│   │   ├── 2.3.init.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.3.init.png~update the structure for gitbook
│   │   ├── 2.4.student_struct.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.4.student_struct.png~update the structure for gitbook
│   │   ├── 2.5.rect_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.rect_func_without_receiver.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_without_receiver.png~update the structure for gitbook
│   │   ├── 3.1.dns2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns2.png~update the structure for gitbook
│   │   ├── 3.1.dns_hierachy.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_hierachy.png~update the structure for gitbook
│   │   ├── 3.1.dns_inquery.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_inquery.png~update the structure for gitbook
│   │   ├── 3.1.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.http.png~update the structure for gitbook
│   │   ├── 3.1.httpPOST.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.httpPOST.png~update the structure for gitbook
│   │   ├── 3.1.response.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.response.png~update the structure for gitbook
│   │   ├── 3.1.web.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web.png~update the structure for gitbook
│   │   ├── 3.1.web2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web2.png~update the structure for gitbook
│   │   ├── 3.2.goweb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.2.goweb.png~update the structure for gitbook
│   │   ├── 3.3.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.http.png~update the structure for gitbook
│   │   ├── 3.3.illustrator.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.illustrator.png~update the structure for gitbook
│   │   ├── 4.1.login.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.login.png~update the structure for gitbook
│   │   ├── 4.1.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.slice.png~update the structure for gitbook
│   │   ├── 4.3.escape.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.3.escape.png~update the structure for gitbook
│   │   ├── 4.4.token.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.4.token.png~update the structure for gitbook
│   │   ├── 4.5.upload.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload.png~update the structure for gitbook
│   │   ├── 4.5.upload2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload2.png~update the structure for gitbook
│   │   ├── 5.6.mongodb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 5.6.mongodb.png~update the structure for gitbook
│   │   ├── 6.1.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie.png~update the structure for gitbook
│   │   ├── 6.1.cookie2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie2.png~update the structure for gitbook
│   │   ├── 6.1.session.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.session.png~update the structure for gitbook
│   │   ├── 6.4.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.cookie.png~update the structure for gitbook
│   │   ├── 6.4.hijack.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijack.png~update the structure for gitbook
│   │   ├── 6.4.hijacksuccess.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijacksuccess.png~update the structure for gitbook
│   │   ├── 6.4.setcookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.setcookie.png~update the structure for gitbook
│   │   ├── 7.4.template.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 7.4.template.png~update the structure for gitbook
│   │   ├── 8.1.socket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.1.socket.png~update the structure for gitbook
│   │   ├── 8.2.websocket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket.png~update the structure for gitbook
│   │   ├── 8.2.websocket2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket2.png~update the structure for gitbook
│   │   ├── 8.2.websocket3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket3.png~update the structure for gitbook
│   │   ├── 8.3.rest.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest.png~update the structure for gitbook
│   │   ├── 8.3.rest2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest2.png~update the structure for gitbook
│   │   ├── 8.3.rest3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest3.png~update the structure for gitbook
│   │   ├── 8.4.rpc.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.4.rpc.png~update the structure for gitbook
│   │   ├── 9.1.csrf.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 9.1.csrf.png~update the structure for gitbook
│   │   ├── cover.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── cover.png~update the structure for gitbook
│   │   ├── ebook.jpg~380a8ee74c41759d8189ad553423467994187253
│   │   ├── ebook.jpg~update the structure for gitbook
│   │   ├── navi1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi1.png~update the structure for gitbook
│   │   ├── navi10.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi10.png~update the structure for gitbook
│   │   ├── navi11.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi11.png~update the structure for gitbook
│   │   ├── navi12.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi12.png~update the structure for gitbook
│   │   ├── navi13.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi13.png~update the structure for gitbook
│   │   ├── navi14.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi14.png~update the structure for gitbook
│   │   ├── navi2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi2.png~update the structure for gitbook
│   │   ├── navi3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi3.png~update the structure for gitbook
│   │   ├── navi4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi4.png~update the structure for gitbook
│   │   ├── navi5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi5.png~update the structure for gitbook
│   │   ├── navi6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi6.png~update the structure for gitbook
│   │   ├── navi7.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi7.png~update the structure for gitbook
│   │   ├── navi8.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi8.png~update the structure for gitbook
│   │   ├── navi9.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi9.png~update the structure for gitbook
│   │   ├── polling.png~380a8ee74c41759d8189ad553423467994187253
│   │   └── polling.png~update the structure for gitbook
│   ├── preface.md
│   └── ref.md
├── fr/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── preface.md
│   └── ref.md
├── ja/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── build.go
│   ├── build.sh
│   ├── config
│   ├── glossary.md
│   ├── images/
│   │   ├── alipay.png~380a8ee74c41759d8189ad553423467994187253
│   │   └── alipay.png~update the structure for gitbook
│   ├── preface.md
│   ├── ref.md
│   └── src/
│       └── 1.2/
│           ├── main.go
│           └── sqrt.go
├── pt-br/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── preface.md
│   └── ref.md
├── ru/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 06.0.md
│   └── preface.md
├── th/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── build.go
│   ├── build.sh
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── eBook/
│   │   ├── 05.0.md
│   │   └── 05.0.md.orig
│   ├── images/
│   │   ├── 1.1.cmd.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.cmd.png~update the structure for gitbook
│   │   ├── 1.1.linux.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.linux.png~update the structure for gitbook
│   │   ├── 1.1.mac.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.mac.png~update the structure for gitbook
│   │   ├── 1.3.go.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.3.go.png~update the structure for gitbook
│   │   ├── 1.4.eclipse1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse1.png~update the structure for gitbook
│   │   ├── 1.4.eclipse2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse2.png~update the structure for gitbook
│   │   ├── 1.4.eclipse3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse3.png~update the structure for gitbook
│   │   ├── 1.4.eclipse4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse4.png~update the structure for gitbook
│   │   ├── 1.4.eclipse5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse5.png~update the structure for gitbook
│   │   ├── 1.4.eclipse6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse6.png~update the structure for gitbook
│   │   ├── 1.4.emacs.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.emacs.png~update the structure for gitbook
│   │   ├── 1.4.idea1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea1.png~update the structure for gitbook
│   │   ├── 1.4.idea2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea2.png~update the structure for gitbook
│   │   ├── 1.4.idea3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea3.png~update the structure for gitbook
│   │   ├── 1.4.idea4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea4.png~update the structure for gitbook
│   │   ├── 1.4.idea5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea5.png~update the structure for gitbook
│   │   ├── 1.4.liteide.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.liteide.png~update the structure for gitbook
│   │   ├── 1.4.sublime1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime1.png~update the structure for gitbook
│   │   ├── 1.4.sublime2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime2.png~update the structure for gitbook
│   │   ├── 1.4.sublime3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime3.png~update the structure for gitbook
│   │   ├── 1.4.sublime4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime4.png~update the structure for gitbook
│   │   ├── 1.4.vim.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.vim.png~update the structure for gitbook
│   │   ├── 13.1.gopath.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath.png~update the structure for gitbook
│   │   ├── 13.1.gopath2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath2.png~update the structure for gitbook
│   │   ├── 13.4.beego.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.4.beego.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap2.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap3.png~update the structure for gitbook
│   │   ├── 14.4.github.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github.png~update the structure for gitbook
│   │   ├── 14.4.github2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github2.png~update the structure for gitbook
│   │   ├── 14.4.github3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github3.png~update the structure for gitbook
│   │   ├── 14.6.pprof.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof.png~update the structure for gitbook
│   │   ├── 14.6.pprof2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof2.png~update the structure for gitbook
│   │   ├── 14.6.pprof3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof3.png~update the structure for gitbook
│   │   ├── 2.2.array.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.array.png~update the structure for gitbook
│   │   ├── 2.2.basic.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.basic.png~update the structure for gitbook
│   │   ├── 2.2.makenew.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.makenew.png~update the structure for gitbook
│   │   ├── 2.2.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice.png~update the structure for gitbook
│   │   ├── 2.2.slice2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice2.png~update the structure for gitbook
│   │   ├── 2.3.init.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.3.init.png~update the structure for gitbook
│   │   ├── 2.4.student_struct.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.4.student_struct.png~update the structure for gitbook
│   │   ├── 2.5.rect_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.rect_func_without_receiver.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_without_receiver.png~update the structure for gitbook
│   │   ├── 3.1.dns2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns2.png~update the structure for gitbook
│   │   ├── 3.1.dns_hierachy.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_hierachy.png~update the structure for gitbook
│   │   ├── 3.1.dns_inquery.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_inquery.png~update the structure for gitbook
│   │   ├── 3.1.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.http.png~update the structure for gitbook
│   │   ├── 3.1.httpPOST.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.httpPOST.png~update the structure for gitbook
│   │   ├── 3.1.response.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.response.png~update the structure for gitbook
│   │   ├── 3.1.web.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web.png~update the structure for gitbook
│   │   ├── 3.1.web2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web2.png~update the structure for gitbook
│   │   ├── 3.2.goweb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.2.goweb.png~update the structure for gitbook
│   │   ├── 3.3.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.http.png~update the structure for gitbook
│   │   ├── 3.3.illustrator.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.illustrator.png~update the structure for gitbook
│   │   ├── 4.1.login.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.login.png~update the structure for gitbook
│   │   ├── 4.1.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.slice.png~update the structure for gitbook
│   │   ├── 4.3.escape.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.3.escape.png~update the structure for gitbook
│   │   ├── 4.4.token.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.4.token.png~update the structure for gitbook
│   │   ├── 4.5.upload.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload.png~update the structure for gitbook
│   │   ├── 4.5.upload2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload2.png~update the structure for gitbook
│   │   ├── 5.6.mongodb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 5.6.mongodb.png~update the structure for gitbook
│   │   ├── 6.1.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie.png~update the structure for gitbook
│   │   ├── 6.1.cookie2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie2.png~update the structure for gitbook
│   │   ├── 6.1.session.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.session.png~update the structure for gitbook
│   │   ├── 6.4.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.cookie.png~update the structure for gitbook
│   │   ├── 6.4.hijack.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijack.png~update the structure for gitbook
│   │   ├── 6.4.hijacksuccess.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijacksuccess.png~update the structure for gitbook
│   │   ├── 6.4.setcookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.setcookie.png~update the structure for gitbook
│   │   ├── 7.4.template.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 7.4.template.png~update the structure for gitbook
│   │   ├── 8.1.socket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.1.socket.png~update the structure for gitbook
│   │   ├── 8.2.websocket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket.png~update the structure for gitbook
│   │   ├── 8.2.websocket2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket2.png~update the structure for gitbook
│   │   ├── 8.2.websocket3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket3.png~update the structure for gitbook
│   │   ├── 8.3.rest.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest.png~update the structure for gitbook
│   │   ├── 8.3.rest2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest2.png~update the structure for gitbook
│   │   ├── 8.3.rest3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest3.png~update the structure for gitbook
│   │   ├── 8.4.rpc.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.4.rpc.png~update the structure for gitbook
│   │   ├── 9.1.csrf.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 9.1.csrf.png~update the structure for gitbook
│   │   ├── cover.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── cover.png~update the structure for gitbook
│   │   ├── ebook.jpg~380a8ee74c41759d8189ad553423467994187253
│   │   ├── ebook.jpg~update the structure for gitbook
│   │   ├── navi1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi1.png~update the structure for gitbook
│   │   ├── navi10.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi10.png~update the structure for gitbook
│   │   ├── navi11.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi11.png~update the structure for gitbook
│   │   ├── navi12.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi12.png~update the structure for gitbook
│   │   ├── navi13.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi13.png~update the structure for gitbook
│   │   ├── navi14.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi14.png~update the structure for gitbook
│   │   ├── navi2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi2.png~update the structure for gitbook
│   │   ├── navi3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi3.png~update the structure for gitbook
│   │   ├── navi4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi4.png~update the structure for gitbook
│   │   ├── navi5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi5.png~update the structure for gitbook
│   │   ├── navi6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi6.png~update the structure for gitbook
│   │   ├── navi7.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi7.png~update the structure for gitbook
│   │   ├── navi8.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi8.png~update the structure for gitbook
│   │   ├── navi9.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi9.png~update the structure for gitbook
│   │   ├── polling.png~380a8ee74c41759d8189ad553423467994187253
│   │   └── polling.png~update the structure for gitbook
│   ├── preface.md
│   ├── ref.md
│   └── src/
│       └── 1.2/
│           ├── main.go
│           └── sqrt.go
├── tr/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── README.md
│   └── preface.md
├── zh/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── a_herf.go
│   ├── a_href.py
│   ├── build-web-application-with-golang.azw3
│   ├── build.go
│   ├── build.sh
│   ├── build_new.go
│   ├── build_new.sh
│   ├── preface.md
│   ├── ref.md
│   └── src/
│       └── 1.2/
│           ├── main.go~HEAD
│           ├── main.go~eead24cf064976b648de5826eab51880c803b0fa
│           ├── sqrt.go~HEAD
│           └── sqrt.go~eead24cf064976b648de5826eab51880c803b0fa
└── zh-tw/
    ├── 01.0.md
    ├── 01.1.md
    ├── 01.2.md
    ├── 01.3.md
    ├── 01.4.md
    ├── 01.5.md
    ├── 02.0.md
    ├── 02.1.md
    ├── 02.2.md
    ├── 02.3.md
    ├── 02.4.md
    ├── 02.5.md
    ├── 02.6.md
    ├── 02.7.md
    ├── 02.8.md
    ├── 03.0.md
    ├── 03.1.md
    ├── 03.2.md
    ├── 03.3.md
    ├── 03.4.md
    ├── 03.5.md
    ├── 04.0.md
    ├── 04.1.md
    ├── 04.2.md
    ├── 04.3.md
    ├── 04.4.md
    ├── 04.5.md
    ├── 04.6.md
    ├── 05.0.md
    ├── 05.1.md
    ├── 05.2.md
    ├── 05.3.md
    ├── 05.4.md
    ├── 05.5.md
    ├── 05.6.md
    ├── 05.7.md
    ├── 06.0.md
    ├── 06.1.md
    ├── 06.2.md
    ├── 06.3.md
    ├── 06.4.md
    ├── 06.5.md
    ├── 07.0.md
    ├── 07.1.md
    ├── 07.2.md
    ├── 07.3.md
    ├── 07.4.md
    ├── 07.5.md
    ├── 07.6.md
    ├── 07.7.md
    ├── 08.0.md
    ├── 08.1.md
    ├── 08.2.md
    ├── 08.3.md
    ├── 08.4.md
    ├── 08.5.md
    ├── 09.0.md
    ├── 09.1.md
    ├── 09.2.md
    ├── 09.3.md
    ├── 09.4.md
    ├── 09.5.md
    ├── 09.6.md
    ├── 09.7.md
    ├── 10.0.md
    ├── 10.1.md
    ├── 10.2.md
    ├── 10.3.md
    ├── 10.4.md
    ├── 11.0.md
    ├── 11.1.md
    ├── 11.2.md
    ├── 11.3.md
    ├── 11.4.md
    ├── 12.0.md
    ├── 12.1.md
    ├── 12.2.md
    ├── 12.3.md
    ├── 12.4.md
    ├── 12.5.md
    ├── 13.0.md
    ├── 13.1.md
    ├── 13.2.md
    ├── 13.3.md
    ├── 13.4.md
    ├── 13.5.md
    ├── 13.6.md
    ├── 14.0.md
    ├── 14.1.md
    ├── 14.2.md
    ├── 14.3.md
    ├── 14.4.md
    ├── 14.5.md
    ├── 14.6.md
    ├── 14.7.md
    ├── README.md
    ├── SUMMARY.md
    ├── a_herf.go
    ├── a_href.py
    ├── build-web-application-with-golang.azw3
    ├── build.go
    ├── build.sh
    ├── build_new.go
    ├── build_new.sh
    ├── preface.md
    ├── ref.md
    └── src/
        └── 1.2/
            ├── main.go
            └── sqrt.go

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

================================================
FILE: LANGS.md
================================================
* [Deutsch](de/)
* [English](en/)
* [Español](es/)
* [Français](fr/)
* [Português - Brasil](pt-br/)
* [Русский](ru/)
* [Türkçe](tr/)
* [বাংলা](bn/)
* [日本語](ja/)
* [中文](zh/)
* [پارسی](fa/)


================================================
FILE: LICENSE.md
================================================
Copyright (c) 2012, AstaXie and The Contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

  * Neither the name of the AstaXie nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: README.md
================================================
# Multiple Language Versions

* [(HTML - PDF) on GitBook](https://astaxie.gitbooks.io/build-web-application-with-golang)
* [Deutsch](de/preface.md)
* [English](en/preface.md)
* [Español](es/preface.md)
* [Français](fr/preface.md)
* [Português - Brasil](pt-br/preface.md)
* [Русский](ru/preface.md)
* [Türkçe](tr/preface.md)
* [বাংলা](bn/preface.md)
* [日本語](ja/preface.md)
* [简体中文](zh/preface.md)
* [正體中文](zh-tw/preface.md)
* [پارسی](fa/preface.md)
* [ภาษาไทย](th/preface.md)

# Donate

AliPay: <img src="zh/images/alipay.png" alt="alipay" width="100" height="100">

English Donate:[donate](http://beego.me/donate)

## Community
QQ群:148647580

BBS:[http://gocn.io/](http://gocn.io/)

## Contributors

- See [contributors page](https://github.com/astaxie/build-web-application-with-golang/graphs/contributors) for full list of contributors.

## Acknowledgments

 - [四月份平民](https://plus.google.com/110445767383269817959) (review代码)
 - [Hong Ruiqi](https://github.com/hongruiqi) (review代码)
 - [BianJiang](https://github.com/border) (编写go开发工具Vim和Emacs的设置)
 - [Oling Cat](https://github.com/OlingCat)(review代码)
 - [Wenlei Wu](mailto:spadesacn@gmail.com)(提供一些图片展示)
 - [polaris](https://github.com/polaris1119)(review书)
 - [雨痕](https://github.com/qyuhen)(review第二章)

## License
Book License: [CC BY-SA 3.0 License](http://creativecommons.org/licenses/by-sa/3.0/)

Code License: [BSD 3-Clause License](<https://github.com/astaxie/build-web-application-with-golang/blob/master/LICENSE.md>)


================================================
FILE: bn/01.0.md
================================================
# ১ গো এনভায়রনমেন্ট কনফিগারেশন

গো এর ভুবনে আপনাকে স্বাগতম! পরম করুণাময় সৃষ্টিকর্তার নামে শুরু করছি।

গো একটি ওপেনসোর্স, কম্পাইল প্রোগ্রামিং ল্যাঙ্গুয়েজ যেটি ২০০৭ সালে রব পাইক, কেন থমসন এবং রবার্ট গ্রিসমার মিলে ডিজাইন করেন। এটি স্ট্যাটিক টাইপ ল্যাঙ্গুয়েজ এবং এর সিনট্যাক্স অনেকটা সি প্রোগ্রামিং ল্যাঙ্গুয়েজ এর মত। গো এর সুবিধাসমূহ নিম্নে দেয়া হলঃ

- অনেক বড় প্রজেক্ট কয়েক সেকন্ডের মধ্যে কম্পাইল করতে পারে
- গারবেজ কালেকশন সুবিধা
- এমন একটা সফটওয়্যার ডেভেলপমেন্ট মডেল প্রদান করে যেটা সি-স্টাইল হেডারের সমস্যা দূর করে
- স্ট্যাটিক ল্যাঙ্গুয়েজ যার টাইপ সিস্টেম এর সীমা নেই। এটা অনেকটা অবজেক্ট-ওরিয়েণ্টেড প্রোগ্রামিং ল্যাঙ্গুয়েজের মত
- গো ল্যাঙ্গুয়েজ লেভেলে কনকারেন্সি এবং কমিউনিকেশন সাপোর্ট করে
- মাল্টি-কোর প্রসেসরের জন্য ডিজাইন করা
- স্ট্রিং এবং ম্যাপ ল্যাঙ্গুয়েজে বিল্টইন দেয়া আছে

গো একটি কম্পাইল ল্যাঙ্গুয়েজ। এটা একই সাথে স্ট্যাটিক ল্যাঙ্গুয়েজের সিকিউরিটি এবং ইন্টারপ্রেটেড ও ডায়নামিক ল্যাঙ্গুয়েজের ডেভেলপমেন্ট সুবিধা প্রদান করে। গো একটি আধুনিক প্রোগ্রামিং ল্যাঙ্গুয়েজ যা নেটওয়ার্কিং ও মাল্টি-কোর সাপোর্ট করে।


পরবর্তী ধাপে আমরা দেখব কিভাবে গো ইনস্টল ও ইনভাইরনমেন্ট কনফিগারেশন করতে হয়।

## লিঙ্ক

- [ডিরেক্টরি](preface.md)
- পরিবর্তী ধাপ: [ইনস্টলেশন](01.1.md)


================================================
FILE: bn/01.1.md
================================================
# ইনস্টলেশন ১.১

## ইনস্টলেশন ১.১
আপনার কম্পিউটারে গো এর পরিবেশ কনফিগার করার অনেক উপায় আছে এবং আপনি আপনার পছন্দ মত যে কোনটি চয়ন করতে পারেন। নিম্নরূপ তিনটি সর্বাধিক প্রচলিত উপায়।

-  অফিসিয়াল ইনস্টলেশন প্যাকেজ।
	- গো  টিম উইন্ডোজ, লিনাক্স, ম্যাক এবং অন্যান্য অপারেটিং সিস্টেমে সুবিধাজনক ইনস্টলেশন প্যাকেজগুলি প্রদান করে। এটি সম্ভবত শুরু করার সবচেয়ে সহজ উপায়। আপনি গোল্যাং ডাউনলোড পেজ  থেকে ইনস্টলার পেতে পারেন।

- সোর্স কোড থেকে এটি ইনস্টল করতে পারেন

    -  এটি ডেভেলপারদের সাথে পরিচিত যারা ইউনিক্স-মত সিস্টেমের সাথে পরিচিত।
- তৃতীয় পক্ষের সরঞ্জাম ব্যবহার করে
	- গো  ইনস্টল করার জন্য অনেক তৃতীয় পক্ষের সরঞ্জাম এবং প্যাকেজ ম্যানেজার রয়েছে, যেমন উবুন্টুতে FT- প্রফিট এবং ম্যাকে হোমব্রো ।
আপনি যদি কম্পিউটারে একাধিক সংস্করণ ইনস্টল করতে চান, তাহলে আপনাকে [GVM](https://github.com/moovweb/gvm) নামক একটি প্যাকেজ ম্যানেজার ইনস্টল করতে হবে। এই কাজের জন্য এটি সবচেয়ে ভালো , অন্যথায় আপনাকে নিজে এটি পরিচালনা করতে হবে।

## সোর্স কোড থেকে ইনস্টল করুন

গো  ১.৫ এবং ঊর্ধ্বগামী কম্পাইল করার জন্য, শুধুমাত্র আপনার গো  এর আগের সংস্করণটি দরকার, যেমনটি বুটস্ট্র্যাপিং অর্জন করেছে। আপনার শুধুমাত্র Go কম্পাইল প্রয়োজন

go ১.৪ নীচের দিকে কম্পাইল করতে,আপনাকে সি সি-কম্পাইলার প্রয়োজন হবে কারণ  গো  এর কিছু অংশ এখনও প্ল্যান 9 সি এবং এটি এন্ড টি এসেম্বারের মধ্যে লেখা আছে।

ম্যাক এ যদি আপনি Xcode ইনস্টল করেন তবে আপনার ইতিমধ্যেই কম্পাইলার আছে।

ইউনিক্স-মত সিস্টেমগুলিতে, আপনি gcc বা অনুরূপ কম্পাইলার ইনস্টল করতে হবে। উদাহরণস্বরূপ, প্যাকেজ ম্যানেজার apt-get (উবুন্টুতে অন্তর্ভুক্ত) ব্যবহার করে, প্রয়োজন অনুসারে প্রয়োজনীয় কম্পাইলার ইনস্টল করতে পারেন:

```sh
sudo apt-get install gcc libc6-dev
```

উইন্ডোজে, আপনার জি.সি.সি. ইনস্টল করার জন্য আপনাকে মিনিগড ইনস্টল করতে হবে। ইনস্টলেশনের পরে আপনার এনভেরিয়েবলগুলি কনফিগার করতে ভুলবেন না। (*** এটির মত দেখায় যে এটি একটি অনুবাদক দ্বারা মন্তব্য করা হয়েছে: যদি আপনি 64-বিট উইন্ডোজ ব্যবহার করছেন তবে আপনাকে 64-বিট সংস্করণটি ইনস্টল করতে হবে MinGW ***)

এই মুহুর্তে, Go সোর্স কোড ক্লোন করতে এবং এটি কম্পাইল করার জন্য নিম্নোক্ত কমান্ডগুলি চালনা করুন (*** এটি আপনার বর্তমান ডিরেক্টরীতে সোর্স কোড ক্লোন করবে। আপনি চালিয়ে যাওয়ার আগে আপনার কাজের পাথ পরিবর্তন করুন। এটি কিছু সময় নিতে পারে। *** )

	git clone https://go.googlesource.com/go
	cd go/src
	./all.bash 

	একটি সফল ইনস্টলেশন  "সমস্ত পরীক্ষা পাস"  বার্তার  সঙ্গে শেষ হবে।

উইন্ডোজে, আপনি 'all.bat` চালানোর মাধ্যমে এটি অর্জন করতে পারেন।

আপনি যদি উইন্ডোজ ব্যবহার করেন, তাহলে ইনস্টলেশনের প্যাকেজটি আপনার ওয়্যারলেস ভেরিয়েবল স্বয়ংক্রিয়ভাবে সেট করবে। ইউনিক্স-মত সিস্টেমগুলিতে, আপনাকে এই ভেরিয়েবলগুলিকে ম্যানুয়ালি সেট করতে হবে। (*** আপনার Go সংস্করণটি 1.0 এর চেয়ে বড় হলে আপনার $ GOBIN সেট করতে হবে না এবং এটি স্বয়ংক্রিয়ভাবে আপনার $ GOROOT / bin এর সাথে সম্পর্কিত হবে, যা আমরা পরবর্তী অংশে আলোচনা করব ***)।

    export GOROOT=$HOME/go
    export GOBIN=$GOROOT/bin
    export PATH=$PATH:$GOROOT/bin

আপনি যদি আপনার পর্দায় নিম্নলিখিত তথ্য দেখতে পান, আপনি সব সেট হয়।

![](images/1.1.mac.png?raw=true)

চিত্র 1.1 সূত্র কোড থেকে ইনস্টল করার পরে তথ্য

একবার আপনি Go এর ব্যবহারের তথ্য দেখেন, এর মানে হল আপনি সফলভাবে ইনস্টল করেছেন আপনার কম্পিউটারে । যদি এটি " কমান্ডের মতো না বলে", তবে পরীক্ষা করুন যে আপনার $ PATH এনভায়রনমেন্ট ভেরিয়েবল Go- এর ইনস্টলেশন পাথ রয়েছে কিনা।

## স্ট্যান্ডার্ড ইনস্টলেশন প্যাকেজ ব্যবহার করে

গো আর  প্রতিটি সমর্থিত অপারেটিং সিস্টেমের জন্য এক ক্লিকে ইনস্টলেশনের প্যাকেজ রয়েছে । এই প্যাকেজটি ডিফল্টভাবে `/ usr / local / go` (` c: \ Go` উইন্ডোজে) চালু হবে। অবশ্যই এই পরিবর্তন করা যেতে পারে, কিন্তু উপরে দেখানো হিসাবে আপনাকে  সব পরিবেশের ভেরিয়েবলগুলি পরিবর্তন করতে হবে।

### আপনার অপারেটিং সিস্টেম 32-বিট বা 64-বিট কিভাবে পরীক্ষা করবেন ?

আমাদের পরবর্তী পদক্ষেপটি আপনার অপারেটিং সিস্টেমের প্রকারের উপর নির্ভর করে, তাই আমাদের  স্ট্যান্ডার্ড ইনস্টলেশন প্যাকেজগুলি ডাউনলোড করার আগে এটি পরীক্ষা করতে হবে।

আপনি যদি উইন্ডোজ ব্যবহার করছেন, তাহলে `win + আর` টিপুন এবং কমান্ড টুলটি রান করুন। `Systeminfo` কমান্ডটি টাইপ করুন এবং এটি আপনাকে কিছু দরকারী সিস্টেম তথ্য দেখাবে। "সিস্টেম type" বলে লাইন খুঁজুন - যদি আপনি "x64- ভিত্তিক পিসি" দেখতে পান যা আপনার অপারেটিং সিস্টেম 64-বিট, 32-বিট নয়। 

আমি ম্যাক ওএসএক্সে 32-বিট প্রসেসরকে আর সমর্থন করি না কেননা আমি ম্যাক ইউজার হিসাবে 64-বিট প্যাকেজটি ডাউনলোড করার জন্য দৃঢ়ভাবে সুপারিশ করছি।

লিনাক্স ব্যবহারকারীরা সিস্টেমের তথ্য দেখতে টার্মিনালে `uname -a` টাইপ করতে পারেন।
একটি 64 বিট অপারেটিং সিস্টেম নিম্নলিখিত দেখাবে:

    <Some Details> x86_64 x86_64 x86_64 GNU / Linux
    // কিছু মেশিন যেমন উবুন্টু 10.04 নিম্নলিখিত হিসাবে প্রদর্শন করা হবে
    x86_64 GNU / লিনাক্স

32-বিট অপারেটিং সিস্টেম পরিবর্তে দেখান:

    <Some Details> i686 i686 i386 GNU / লিনাক্স

### ম্যাক

[ডাউনলোড পেজ ] (https://golang.org/dl/) এ যান, 32 বিট সিস্টেমের জন্য `go1.4.2.darwin-386.pkg` (পরবর্তী সংস্করণে 32-বিট ডাউনলোড নেই।) নির্বাচন করুন এবং `go1.8.3.darwin-amd64.pkg` 64 বিট সিস্টেমের জন্য। "পরবর্তী" ক্লিক করে শেষ পর্যন্ত সব পথ ধরে, আপনার সিস্টেমের $ PATH- এ যোগ করার পরে `~ / go / bin 'যোগ করা হবে। এখন টার্মিনাল খুলুন এবং `go` টাইপ করুন। আপনি চিত্র 1.1 এ প্রদর্শিত একই আউটপুট দেখতে হবে।

### লিনাক্স

[ডাউনলোড পেজ] (https://golang.org/dl/) এ যান, 32-বিট সিস্টেমের জন্য `go1.8.3.linux-386.tar.gz` এবং` go1.8.3.linux-amd64.tar নির্বাচন করুন 64-বিট সিস্টেমের জন্য .gz`। ধরুন আপনি '$ GO_INSTALL_DIR' পথে গিয়ে ইনস্টল করতে চান। `Tar zxvf go1.8.3.linux-amd64.tar.gz -C $ GO_INSTALL_DIR` কমান্ডের সাহায্যে আপনার নির্বাচিত পাথে` tar.gz` আনকম্প্রেস করুন। তারপরে আপনার $ PATH সেট করুন: 'রপ্তানি PATH = $ PATH: $ GO_INSTALL_DIR / go / bin' এখন শুধু টার্মিনাল খুলুন এবং `go` টাইপ করুন আপনি এখন চিত্র 1.1 এ প্রদর্শিত একই আউটপুট দেখতে হবে।

### উইন্ডোজ

[ডাউনলোড পেজ] (https://golang.org/dl/) এ যান, 32 বিট সিস্টেমের জন্য `go1.8.3.windows-386.msi` এবং` go1.8.3.windows-amd64.msi` নির্বাচন করুন 64-বিট সিস্টেম "পরবর্তী" ক্লিক করে শেষ পর্যন্ত সমস্ত পথ ধরে, `c: / go / bin '` পাথ' এ যোগ করা হবে। এখন শুধু একটি কমান্ড লাইন উইন্ডো খুলুন এবং `go` টাইপ করুন আপনি এখন চিত্র 1.1 এ প্রদর্শিত একই আউটপুট দেখতে হবে।

## তৃতীয় পক্ষের সরঞ্জামগুলি ব্যবহার করুন

### জিএমএম

GVM একটি গৌণ সংস্করণ নিয়ন্ত্রণ সরঞ্জাম যা তৃতীয় পক্ষের দ্বারা তৈরি হয়, যেমন রুবি জন্য rvm। এটি ব্যবহার করতে বেশ সহজ। আপনার টার্মিনালে নিম্নোক্ত কমান্ডগুলি লিখে gvm ইনস্টল করুন:

    bash < <(curl -s -S -L https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)

তারপর আমরা নিম্নলিখিত কমান্ড ব্যবহার করে ইনস্টল করবো :

    gvm install go1.8.3
    gvm use go1.8.3

এই প্রক্রিয়াটি সম্পূর্ণ হওয়ার পরে, আপনার সব সেট আছে।

### Apt-get

উবুন্টু লিনাক্সের সবচেয়ে জনপ্রিয় ডেস্কটপ রিলিজ সংস্করণ। এটি প্যাকেটগুলি পরিচালনার জন্য `apt-get` ব্যবহার করে। আমরা নিম্নলিখিত কমান্ড ব্যবহার করে Go ইনস্টল করতে পারি 

    sudo add-apt-repository ppa:gophers/go
    sudo apt-get update
    sudo apt-get install golang-go

### wget
```sh

wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
sudo tar -xzf go1.8.3.linux-amd64.tar.gz -C /usr/local 

# Go environment
export GOROOT=/usr/local/go
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOBIN
export GOPATH=$HOME/gopath 
```    

1.8 থেকে শুরু করে, GOPATH এনভায়রনমেন্ট ভেরিয়েবলটি এখন যদি সেট না থাকে তবে একটি ডিফল্ট মান থাকে। এটা ইউনিক্সে `$ HOME / go` এবং Windows এ`% USERPROFILE% / go` এ ডিফল্ট।
### Homebrew

Homebrew একটি সফটওয়্যার ম্যানেজমেন্ট টুল যা সাধারণত প্যাকেজগুলি পরিচালনার জন্য ম্যাকে ব্যবহৃত হয়। Go ইনস্টল করার জন্য নিম্নোক্ত কমান্ডগুলি টাইপ করুন। 

১. হোমব্রু ইনস্টল করুন

```sh
     /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

২. গো ইনস্টল করুন

```sh
    brew update && brew upgrade
    brew install go
```
## লিঙ্ক

- [ডিরেক্টরি](preface.md)
- আগের অধ্যায়: [গো এনভায়রনমেন্ট কনফিগারেশন](01.0.md)
- পরিবর্তী ধাপ: [$GOPATH and workspace](01.2.md)
 


================================================
FILE: bn/preface.md
================================================
- ১.[গো এনভায়রনমেন্ট কনফিগারেশন](01.0.md)
	- ১.১. [ইনস্টলেশন](01.1.md)
	- ১.২. [গো-পাথ এবং ওয়ার্কস্পেস](01.2.md)
	- ১.৩. [গো কমান্ড](01.3.md)
	- ১.৪. [গো ডেভেলপমেন্ট টুলস](01.4.md)
	- ১.৫. [সারমর্ম](01.5.md)
- ২.[গো প্রাথমিক জ্ঞান](02.0.md)
	- ২.১. ["হ্যালো, গো"](02.1.md)
	- ২.২. [গো পটভূমি](02.2.md)
	- ২.৩. [কন্ট্রোল স্টেটমেন্ট এবং ফাংশন](02.3.md)
	- ২.৪. [স্ট্রাক্ট](02.4.md)
	- ২.৫. [অবজেক্ট-ওরিয়েন্টেড](02.5.md)
	- ২.৬. [ইন্টারফেস](02.6.md)
	- ২.৭. [কনকারেন্সি](02.7.md)
	- ২.৮. [সারমর্ম](02.8.md)
- ৩.[ওয়েব ফাউন্ডেশন](03.0.md)
	- ৩.১. [ওয়েবে কাজ করার ভিত্তি](03.1.md)
	- ৩.২. [একটি সাধারণ ওয়েব সার্ভার তৈরি করা](03.2.md)
	- ৩.৩. [গো কিভাবে ওয়েবে কাজ করে](03.3.md)
	- ৩.৪. [http প্যাকেজ সম্পর্কে জানা](03.4.md)
	- ৩.৫. [সারমর্ম](03.5.md)
- ৪.[ইউজার ফর্ম](04.0.md)
	- ৪.১. [ফর্ম ইনপুট প্রকিয়াকরন](04.1.md)
	- ৪.২. [ইনপুট ভেরিফাই করা](04.2.md)
	- ৪.৩. [ক্রস সাইট স্ক্রিপটিং](04.3.md)
	- ৪.৪. [ডুপ্লিকেট সাবমিশন](04.4.md)
	- ৪.৫. [ফাইল আপলোড](04.5.md)
	- ৪.৬. [সারমর্ম](04.6.md)
- ৫.[ডেটাবেস](05.0.md)
	- ৫.১. [ডেটাবেস/এসকিউএল ইন্টারফেস](05.1.md)
	- ৫.২. [মাইসিক্যুয়েল](05.2.md)
	- ৫.৩. [সিক্যুয়েলাইট](05.3.md)
	- ৫.৪. [পোস্টগ্রেস](05.4.md)
	- ৫.৫. [beedb এর উপর ভিত্তি করে ওআরএম তৈরি করা](05.5.md)
	- ৫.৬. [নো-সিক্যুয়েল ডেটাবেস](05.6.md)
	- ৫.৭. [সারমর্ম](05.7.md)
- ৬.[ডেটা ষ্টোরেজ](06.0.md)
	- ৬.১. [সেশন এবং কুকি](06.1.md)
	- ৬.২. [কিভাবে গোতে সেশন ব্যবহার করতে হয়](06.2.md)
	- ৬.৩. [সেশন ষ্টোরেজ](06.3.md)
	- ৬.৪. [সেশন হাইজ্যাক প্রতিরোধ](06.4.md)
	- ৬.৫. [সারমর্ম](06.5.md)
- ৭.[টেক্সট ফাইল](07.0.md)
	- ৭.১. [এক্সএমএল](07.1.md)
	- ৭.২. [জেসন](07.2.md)
	- ৭.৩. [রেগুলার এক্সপ্রেশন](07.3.md)
	- ৭.৪. [টেমপ্লেট](07.4.md)
	- ৭.৫. [ফাইল](07.5.md)
	- ৭.৬. [স্ট্রিং](07.6.md)
	- ৭.৭. [সারমর্ম](07.7.md)
- ৮.[ওয়েব সার্ভিস](08.0.md)
	- ৮.১. [সকেট](08.1.md)
	- ৮.২. [ওয়েবসকেট](08.2.md)
	- ৮.৩. [রেস্ট](08.3.md)
	- ৮.৪. [আরপিসি](08.4.md)
	- 8.৫. [সারমর্ম](08.5.md)
- ৯.[সিকিউরেটি এবং এনক্রিপশন](09.0.md)
	- ৯.১. [সিএসআরএফ অ্যাটাক](09.1.md)
	- ৯.২. [ইনপুট ফিল্টার](09.2.md)
	- ৯.৩. [এক্সএসএস অ্যাটাক](09.3.md)
	- ৯.৪. [এসকিউএল ইনজেকশন](09.4.md)
	- ৯.৫. [পাসওয়ার্ড ষ্টোরেজ](09.5.md)
	- ৯.৬. [ডাটা এনক্রিপ্ট](09.6.md)
	- ৯.৭. [সারমর্ম](09.7.md)
- ১০.[লোকালাইজেশন](10.0.md)
	- ১০.১ [টাইম জোন](10.1.md)
	- ১০.২ [রিসোর্স লোকালাইজেশন](10.2.md)
	- ১০.৩ [আন্তজাতিক ওয়েব সাইট](10.3.md)
	- ১০.৪ [সারমর্ম](10.4.md)
- ১১.[এরর হ্যান্ডেলিং, ডিবাগ এবং টেস্টিং](11.0.md)
	- ১১.১. [এরর হ্যান্ডেলিং](11.1.md)
	- ১১.২. [GDB ব্যবহার করে ডিবাগ করা](11.2.md)
	- ১১.৩. [টেস্ট কেইস লেখা](11.3.md)
	- ১১.৪. [সারমর্ম](11.4.md)
- ১২.[ডেপলয় এবং মেন্টেনেস](12.0.md)
	- ১২.১. [লগ](12.1.md)
	- ১২.২. [এরর এবং ক্রাশ](12.2.md)
	- ১২.৩. [ডেপলয়](12.3.md)
	- ১২.৪. [ব্যাকআপ এবং রিকভারী](12.4.md)
	- ১২.৫. [সারমর্ম](12.5.md)
- ১৩.[ওয়েব ফ্রামওয়ার্ক তৈরি করা](13.0.md)
	- ১৩.১. [প্রজেক্ট প্রোগ্রাম](13.1.md)
	- ১২.২. [কাস্টম রাউটার](13.2.md)
	- ১২.৩. [কনট্রলার ডিজাইন](13.3.md)
	- ১২.৪. [লগ এবং কনফিগারেশন](13.4.md)
	- ১২.৫. [ব্লগ তৈরি, আপডেট এবং ডিলিট](13.5.md)
	- ১২.৬. [সারমর্ম](13.6.md)
- ১৪.[ওয়েব ফ্রামওয়ার্ক উন্নতি করা](14.0.md)
	- ১৪.১. [স্ট্যাটিক ফাইল](14.1.md)
	- ১৪.২. [সেশন](14.2.md)
	- ১৪.৩. [ফর্ম](14.3.md)
	- ১৪.৪. [ইউজার ভ্যালিডেশন](14.4.md)
	- ১৪.৫. [একাধিক ভাষা](14.5.md)
	- ১৪.৬. [পিপ্রফ](14.6.md)
	- ১৪.৭. [সারমর্ম](14.7.md)
- অ্যাপেন্ডিক্স [রেফারেন্স](ref.md)


================================================
FILE: bn/ref.md
================================================
# Appendix A References

This book is a summary of my Go experience, some content are from other Gophers' either blogs or sites. Thanks to them!

1. [golang blog](http://blog.golang.org)
2. [Russ Cox's blog](http://research.swtch.com/)
3. [go book](http://go-book.appsp0t.com/)
4. [golangtutorials](http://golangtutorials.blogspot.com)
5. [轩脉刃de刀光剑影](http://www.cnblogs.com/yjf512/)
6. [Go Programming Language](http://golang.org/doc/)
7. [Network programming with Go](http://jan.newmarch.name/go/)
8. [setup-the-rails-application-for-internationalization](http://guides.rubyonrails.org/i18n.html#setup-the-rails-application-for-internationalization)
9. [The Cross-Site Scripting (XSS) FAQ](http://www.cgisecurity.com/xss-faq.html)


================================================
FILE: de/01.0.md
================================================
# 1 Einrichtung der Go Entwicklungsumgebung

Willkommen in der Welt von Go. Lass sie uns erforschen.

Go ist eine schnell kompilierte, automatisch speicherbereinigte, multitaskingfähige Programmiersprache. Sie hat folgende Vorteile:

- Kompiliert große Projekte binnen Sekunden
- Bietet ein einfaches Model zur Softwareentwicklung, welches die meisten Probleme um C-ähnliche Probleme mit Header-Dateien vermeidet
- Sie ist eine statische Sprache ohne vielschichte Ebenen im Datentypensystem, sodass Benutzer nicht viel Zeit damit verschwenden, Verbindungen zwischen Datentypen herauszufinden. Es ist mehr wie eine leichtgewichtige, objekt-orientierte Programmiersprache.
- Führt eine automatische Speicherbereinigung (Garbage Collection) durch. Sie bietet grundlegende Unterstützung für das parallele Ausführen von Aufgaben und die Kommunikation zwischen diesen.
- Entworfen für Computer mit mehreren Rechnenkernen.


Go ist eine kompilierte Sprache. Sie vereint während der Entwicklung die Effizienz von dynamischen Programmiersprachen mit der Sicherheit von statischen Sprachen. Sie ist die erste Wahl für moderne, mit Mehrkernprozessoren ausgestatten Computern, welche für die Netzwerkprogrammierung genutzt werden. Um diesen Anforderungen gerecht zu werden, müssen grundsätzliche Probleme in einer solchen Sprache gelöst werden. Dazu zählen ein ausdruckstarkes und zugleich leichtgewichtiges Datentypensystem, native Unterstützung zum simultanen Ausführen von Aufgaben und eine stark regulierte, automatische Speicherbereinigung. Eine lange Zeit gab es keine Packages oder andere Werkzeuge, mit dem Ziel, die genannten Probleme elegant zu lösen. Dies war letztendlich die Motivation, um Go zu entwicklen.

In diesem Kapitel werde ich Dir zeigen, wie Du Deine eigene Go-Entwicklungsumgebung installierst und einrichtest.

## Links

- [Inhaltsverzeichnis](preface.md)
- Nächster Abschnitt: [Installation](01.1.md)


================================================
FILE: de/01.1.md
================================================
# 1.1 Installation

## Drei Wege Go zu installieren

Es gibt viele Wege, um eine Go-Entwicklungsumgebung auf Deinem Computer einzurichten und Du kannst die auswählen, welche Dir gefällt. Die Folgenden sind die drei Häufigsten:

- Offizielle Installationspakete.
    - Das Team um Go stellt praktische Installationspakete für Windows, Linux, Mac und andere Betriebssysteme zur Verfügung. Dies ist wahrscheinlich der einfachste Weg, um zu starten.
- Eigenhändige Kompilierung des Quellcodes.
    - Beliebt untern Entwicklern, die mit UNIX-ähnlichen Systemen vertraut sind.
- Nutze Programme von Dritten.
    - Da Draußen gibt es eine Menge Werkzeuge von Drittanbietern und Paketmanager, um Go zu installieren, wie apt-get in Ubuntu oder homebrew für Mac.


Im Fall, dass Du mehr als eine Version von Go auf Deinem Computer installieren möchtest, dann empfehle ich Dir, einen Blick auf [GVM](https://github.com/moovweb/gvm) zu werfen. Es ist die bisher beste Möglichkeit, die ich soweit gesehen habe, um dies zu tun. Andernfalls musst Du diese Aufgabe selbst bewältigen. 


## Eigenhändige Kompilierung des Quellcodes

Da einige Bestandteile von Go in Plan 9 C und AT&T Assembler geschrieben sind, musst Du einen C-Compiler installieren, bevor Du den nächsten Schritt durchführst.

Auf dem Mac, sofern Du Xcode installiert hast, ist bereits ein entsprechender Compiler vorhanden.


Auf UNIX-ähnlichen Systemen musst Du gcc oder einen vergleichbaren Compiler installieren. Zum Beispiel mit dem Paketmanager apt-get (welcher in Ubuntu integriert ist), kannst Du die benötigten Compiler wie folgt installieren:

`sudo apt-get install gcc libc6-dev`


In Windows wird MinGW vorrausgesetzt, um folglich gcc zu installieren. Vergiss nicht, die Umgebungsvariablen nach der Installation zu konfigurieren. ( ***Alles was so aussieht wie dies, ist eine Anmerkung von den Übersetzern: Wenn Du eine 64-Bit Version von Windows nutzt, solltest Du auch eine 64-Bit Variante von MinGW installieren.*** )

Zu diesem Zeitpunkt, führe die folgenden Befehle aus, um Gos Quellcode zu "klonen" und zu kompilieren. ( ***Der Quellcode wird in Dein aktuelles Arbeitsverzeichnis "geklont". Wechsle dieses, bevor Du fortfährst. Es könnte eine Weile dauern.***)

	git clone https://go.googlesource.com/go
	cd go/src
	./all.bash 
	

Eine erfolgreiche Installation wird mit der Nachricht "ALL TESTS PASSED." beendet.

In Windows kannst Du das Selbe erreichen, indem Du `all.bat` ausführst. 

Wenn Du Windows nutzt, richtet die Installationsroutine die Umgebungsvariablen automatisch ein. Auf UNIX-ähnlichen Systemen musst Du diese wie folgt manuell setzen. ( ***Nutzt Du Go 1.0 oder höher, dann brauchst Du $GOBIN nicht zu definieren, da diese Umgebungsvariable relativ zu $GOROOT/bin gesetzt wird, welche wir im nächsten Abschnitt behandeln werden.*** )

    export GOROOT=$HOME/go
    export GOBIN=$GOROOT/bin
    export PATH=$PATH:$GOROOT/bin

Wenn Du die folgenden Informationen auf Deinem Bildschirm siehst, ist alles erfolgreich verlaufen. 

![](images/1.1.mac.png?raw=true)

Abbildung 1.1 Informationen nach der manuellen Installation vom Quellcode

Sobald Du Informationen zur Nutzung von Go siehst, bedeutet dies, dass Du Go erfolgreich auf Deinem Computer installiert hast. Steht dort jedoch "no such command", überprüfe die $PATH Umgebungsvariable und schaue, ob Sie den Installationspfad von Go beinhaltet.

## Nutze die offiziellen Installationspakete

Go bietet auch Ein-Klick-Installationspakete für jedes unterstützte Betriebssystem. Dieser Vorgang wird Go standardmäßig unter `/usr/local/go` (oder `C:\Go` unter Windows) installieren. Natürlich kannst Du dies nach belieben anpassen, jedoch musst Du die Umgebungsvariablen wie oben gezeigt von Hand ändern. 

### Wie überprüfe ich, ob mein Betriebssystem eine 32-Bit oder 64-Bit Variante ist?

Der nächste Schritt hängt von der Art Deines Betriebssystems ab. Deshalb müssen wir diese erst herausfinden, bevor wir mit der Installation beginnen.

Unter Windows, drücke `Win+R` und öffne die Kommandozeile, indem du `cmd` eingibst und `Enter` drückst. Tippe nun `systeminfo` ein und Du wirst ein paar nützliche Informationen vorfinden. Suche nach der Zeile "Systemtyp", welche die benötigten Informationen beinhaltet. Wenn Du "x64-based PC" liest, besitzt Du ein 64-Bit System, andernfalls ist es eine 32-Bit Version.

Ich empfehle Dir dringlichst die 64-Bit Version von Go herunterzuladen, solltest Du ein Mac-Benutzer sein, da Go keine reinen 32-Bit-Prozessoren mehr unter Mac OSX unterstützt.

Linux-Benutzer können `uname -a` im Terminal eintippen, um die Systeminformationen einzusehen. Ein 64-Bit Betriebssystem wird folgendes anzeigen:

    <Irgendeine Beschreibung> x86_64 x86_64 x86_64 GNU/Linux
    // Einige Computer mit Ubuntu 10.04 werden folgendes ausgeben
    x86_64 GNU/Linux

Ein 32-Bit System sieht dagegen folgendermaßen aus:

    <Irgendeine Beschreibung> i686 i686 i386 GNU/Linux

### Mac

Rufe die Seite zum [Herunterladen](https://golang.org/dl/) auf und wähle `go1.4.2.darwin-386.pkg` für 32-Bit Systeme und `go1.4.2.darwin-amd64.pkg` für 64-Bit Systeme. Installiere Go, indem Du immer auf "weiter" klickst. `~/go/bin` wird automatisch zur Umgebungsvariable $PATH Deines Systems am Ende der Installation hinzugefügt. Öffne nun ein Terminal und tippe `go` ein. Du solltest die selben Ausgaben wie in Abbildung 1.1 sehen.

### Linux


Rufe die Seite zum [Herunterladen](https://golang.org/dl/) auf und wähle `go1.4.2.linux-386.tar.gz` für 32-Bit Systeme und `go1.4.2.linux-amd64.tar.gz` für 64-Bit Systeme. Angenommen, Du willst Go im `$GO_INSTALL_DIR` Pfad installieren: entpacke das `tar.gz` Archiv und wähle Deinen Pfad mit dem Befehl `tar zxvf go1.4.2.linux-amd64.tar.gz -C $GO_INSTALL_DIR`. Dann setze die Umgebungsvariable $PATH mit `export PATH=$PATH:$GO_INSTALL_DIR/go/bin`. Öffne nun ein Terminal und gib `go` ein. Du solltest die selben Ausgaben wie in Abbildung 1.1 sehen.

### Windows

Rufe die Seite zum [Herunterladen](https://golang.org/dl/) auf und wähle `go1.4.2.windows-386.msi` für 32-Bit Systeme und `go1.4.2.windows-amd64.msi` für 64-Bit Systeme. Installiere Go, indem Du immer auf "weiter" klickst. `c:/go/bin` wird zu `path` hinzugefügt. Öffne nun ein Terminal und tippe `go` ein. Du solltest die selben Ausgaben wie in Abbildung 1.1 sehen.

## Nutze Programme von Dritten

### GVM

GVM ist ein Multi-Versions-Kontroll-Werkzeug'für Go und wurde von einem unabhängigen Programmier entwickelt, wie rvm für Ruby. Es ist ziemlich einfach zu nutzen. Installiere gvm indem Du folgendes in ein Terminal eingibst:

    bash < <(curl -s -S -L https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)

Dann installieren wir Go wie folgt:

    gvm install go1.4.2
    gvm use go1.4.2

Ist die Installation abgeschlossen, sind wir auch schon fertig.

### apt-get

Ubuntu ist die beliebteste Desktopvariante für Linux. Es nutzt `apt-get`, um Pakete zu verwalten. Wir können Go mit den unten stehenden Befehlen installieren:

    sudo add-apt-repository ppa:gophers/go
    sudo apt-get update
    sudo apt-get install golang-stable

### Homebrew

Homebrew ist ein oftmals auf dem Mac genutztes Programm, um Pakete zu verwalten. Gib einfach folgendes ein, um Go zu installieren:

    brew install go

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Einrichtung der Go Entwicklungsumgebung](01.0.md)
- Nächster Abschnitt: [$GOPATH und Workspaces](01.2.md)


================================================
FILE: de/01.2.md
================================================
# 1.2 $GOPATH und Workspaces

## $GOPATH

Alle Go-Befehle bauen auf einer wichtigen Umgebungsvariable mit dem Namen $GOPATH. Bedenke, dass es sich nicht um $GOROOT, also den Installationspfad von Go, handelt. Diese Variable verweist vielmehr auf den Go Workspace auf Deinem Computer (Ich benutze den unten stehenden Pfad auf meinem Computer; solltest Du eine andere Ordnerstruktur haben, musst Du den Pfad anpassen).

In UNIX-ähnlichen System sollte die Variable dieser ähnlich sein:

	export GOPATH=/home/apple/mygo

In Windows musst Du eine neue Umgebungsvariable mit dem Namen $GOPATH erstellen und ihren Wert auf `C:\mygo`( ***Dieser Wert ist abhängig von dem Pfad Deines Workspaces*** ) setzen.

Es ist in Ordnung, mehr als einen Pfad (bzw. Workspace) im $GOPATH zu speichern, aber bedenke, dass Du die Pfade mit `:` (oder `;` unter Windows) von einander trennen musst. `go get` wird Pakete stets unter dem ersten, angegebenen Workspace speichern.

IM $GOPATH müssen die drei bestimmte Verzeichnisse vorhanden sein:

- `src` für Quellcode mit der Dateiendung .go, .c, .g, .s.
- `pkg` für kompilierte Dateien mit der Dateiendung .a.
- `bin` für ausführbare Dateien


In diesem Buch ist `mygo` mein einziger Pfad in $GOPATH.

## Paketverzeichnis

Erstelle Quellcodedateien und Ordner wie `$GOPATH/src/mymath/sqrt.go` (`mymath` ist der Paketname) ( ***Der Autor nutzt `mymath` als Paketnamen und gibt den Verzeichnissen, welche die Quellcodedateien beinhalten, den selben Namen***).

Jedes Mal, wenn Du ein neues Paket erstellt, solltest Du einen neuen Ordner im `src` Verzeichnis erstellen. Diese Ordner haben überlicherweise den selben Namen, wie das Paket, welches Du nutzen möchtest. Die Verzeichnisse können zudem beliebig verschachtelt werden. Erstellst Du beispielsweise das Verzeichnis `$GOPATH/src/github.com/astaxie/beedb`, dann wäre das entsprechende Paket `github.com/astaxie/beedb`. Das Paket ist immer das letzte Verzeichnis im Pfad, in diesem Fall `beedb`.

Führe die Folgenden Befehle aus. ( ***Nun widmet sich der Autor wieder den praktischen Dingen.*** )

	cd $GOPATH/src
	mkdir mymath
	
Erstelle eine neue Datei mit dem Namen `sqrt.go`, die folgendes beinhalten soll.

	// Quellcode von $GOPATH/src/mymath/sqrt.go
	package mymath
	
	func Sqrt(x float64) float64 {
		z := 0.0
		for i := 0; i < 1000; i++ {
			z -= (z*z - x) / (2 * x)
		}
		return z
	}
	
Nun haben wir das Paketverzeichnis und den dazugehörigen Quellcode. Ich empfehle Dir, alle Paketverzeichnisse nach dem Paket selbst zu benennen und den gesamten, dazugehörigen Quellcode dort zu speichern.

## Pakete kompilieren

Oben haben wir bereits unser Paket erstellt, aber wie kompilieren wir es, um es nutzen zu können? Dafür gibt es zwei Wege.

1. Navigiere im Terminal zum Paketverzeichnis und führe den `go install` Befehl aus.
2. Führe den oberen Befehl aus, diesmal jedoch mit einem Dateinamen wie `go install mymath`.


Nach der Kompilierung können wir den folgenden Ordner öffnen.

	cd $GOPATH/pkg/${GOOS}_${GOARCH}
	// Wie Du siehst, wurde eine neue Datei erstellt
	mymath.a
	
Die Datei mit der Endung `.a` ist die Binärdatei unseres Pakets. Aber wie nutzen wie diese nun?

Logischerweise müssen wir dafür eine neue Anwendung schreiben, um das Paket zu nutzen.

Erstelle ein neues Paket für die Anwendung mit dem Namen `mathapp`.

	cd $GOPATH/src
	mkdir mathapp
	cd mathapp
	vim main.go
	
Und der Code: 

	// Quellcode von $GOPATH/src/mathapp/main.go 
	package main
	
	import (
		"mymath"
		"fmt"
	)
	
	func main() {
		fmt.Printf("Hallo, Welt. Sqrt(2) = %v\n", mymath.Sqrt(2))
	}
	
Um die Anwendung zu kompilieren, müssen wir zurück in das Verzeichnis, in welchem die Anwendung liegt; in diesem diesem Falle unter `$GOPATH/src/mathapp`. Führe nun den Befehl `go install` aus. Nun solltest Du eine neue ausführbare Datei mit dem Namen `mathapp` im Verzeichnis `$GOPATH/bin/` vorfinden. Um das Programm auszuführen, tippe den Befehl `./mathapp` ein. Im Terminal solltest Du nun den unteren Text lesen können.

	Hallo, Welt. Sqrt(2) = 1.414213562373095
	
## Installation von Paketen Dritter (Remote Packages)

Go umfasst ein Werkzeug zum Installieren von Remote Packages, also Paketen die von anderen Programmierern erstellt wurden. Mit dem Befehl `go get` kannst Du diese für die eigene Nutzung installieren. Es unterstützt die meisten Open Source Communities wie GitHub, Google Code, Bitbucket und Launchpad.

	go get github.com/astaxie/beedb
	
Du kannst `go get -u …` nutzen, um ein Remote Package zu aktualisieren. Zugleich werden auch alle benötigten Abhängigkeiten mit installiert.

Dieser Befehl nutzt verschiedene Versionskontrollsysteme für die verschiedenen Open Source Plattformen. So wird beispielsweise `git` für GitHub und `hg` für Google Code verwendet. Daher musst Du zuerst die entsprechenden Versionskontrollsysteme installieren, ehe Du `go get` nutzen kannst.

Nach dem Ausführen der oben gezeigten Befehle, sollte die Orderstruktur etwa so aussehen.

	$GOPATH
		src
		 |-github.com
		 	 |-astaxie
		 	 	 |-beedb
		pkg
		 |--${GOOS}_${GOARCH}
		 	 |-github.com
		 	 	 |-astaxie
		 	 	 	 |-beedb.a
		 	 	 	 
Im Hintergrund "klont" `go get` den Quellcode nach $GOPATH/src auf deinem Computer und nutzt dann `go install` zur Installation der Remote Packages.

Du kannst Remote Packages wie lokale Pakete nutzen. 

	import "github.com/astaxie/beedb"
	
## Die komplette Verzeichnisstruktur

Wenn Du alle Schritte befolgt hast, sollte Deine Verzeichnisstruktur wie folgt aussehen.

	bin/
		mathapp
	pkg/
		${GOOS}_${GOARCH}, such as darwin_amd64, linux_amd64
      mymath.a
      github.com/
        astaxie/
          beedb.a
	src/
		mathapp
			main.go
		mymath/
			sqrt.go
		github.com/
			astaxie/
				beedb/
					beedb.go
					util.go
					
Nun kannst Du die Ordnerstruktur klar erkennen. `bin` beinhaltet alle ausführbaren Dateien, `pkg` alle compilierten Dateien und `src` den Quellcode der Pakete.

(Das Format von Umgebungsvariable unter Windows ist `%GOPATH%`. Da dieses Buch sich jedoch am UNIX-Stil orientiert, müssen Windowsnutzer das Format von Hand ändern.)

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Installation](01.1.md)
- Nächster Abschnitt: [Go Befehle](01.3.md)


================================================
FILE: de/01.3.md
================================================
# 1.3 Go Befehle

## Go Befehle

Die Programmiersprache Go bringt viele nützliche Befehle für diverse Anwendungszwecke mit sich. Du erhälst eine Übersicht, indem Du `go` im Terminal ausführst.

![](images/1.3.go.png?raw=true)

Figure 1.3 Eine detaillierte Übersicht aller Go Befehle

Jeder Befehl kann nützlich für uns sein. Betrachten wir den Anwendungszweck von ein paar Befehlen.

## go build

Dieser Befehl ist für die Kompilierung und das Testen des Quellcodes verantwortlich. Abhängige Pakete werden ebenfalls mit kompiliert, sofern dies nötig ist.

- Wenn das Paket nicht `main` entspricht, wie unser `mymath` Paket aus Abschnitt 1.2 nicht ausgeführt, nachdem Du `go build` ausgeführt hast. Solltest Du Paket-Dateien mit der Endung `.a` in `$GOPATH/pkg`, nutze stattdessen `go install`.
- Sollte das Paket `main` entsprechen, dann wird eine ausführbare Binärdatei im selben Verzeichnis generiert. Möchtest Du stattdessen, dass Die Binärdatei in `$GOPATH/bin` generiert wird, nutze den Befehl `go install` oder `go build -o ${PATH_HERE}/a.exe.`.
- Befinden sich viele Dateien in einem Ordner, aber Du möchtest nur eine bestimmte Datei kompilieren, dann füge den Dateinamen am Ende von `go build` hinzu. Ein Beispiel wäre `go build a.go`. `go build` wird alle Dateien im selben Ordner kompilieren.
- Du kannst alternativ auch den Namen der ausführbaren Binärdatei ändern. So erhält das `mathapp` Projekt (aus Abschnitt 1.2) mit dem Befehl `go build -o astaxie.exe` den Namen `astaxie.exe`, statt `mathapp.exe`. Der Standardname ist immer der Verzeichnisname (sofern es kein `main` Paket ist) oder der Name der ersten, ausführbaren Datei (`main` Paket). 

Laut den [Spezifikationen der Go Programmiersprache](https://golang.org/ref/spec) sollten Pakete den Namen tragen, der nach dem Schlüsselwort `package` in der ersten Zeile einer Quellcodedatei steht. Dieser muss nicht gleich dem Verzeichnisnamen sein und die ausführbare Binärdatei wird standardmäßig den Verzeichnisnamen annehmen.

- `go build` ignoriert Dateien, die mit `_` oder `.` beginnen.
- Möchtest Du für jedes Betriebssystem andere Quellcodedateien erstellen, dann kannst Du den Systemnamen als Suffix im Dateinamen verwenden. Stell Dir vor, Du hast Quellcodedateien zum Laden von Arrays. Sie könnten nach dem folgenden Schema benannt sein:
	
	array_linux.go | array_darwin.go | array_windows.go | array_freebsd.go
	
`go build` wählt als Suffix den Namen, der mit Deinem Betriebssystem assoziiert ist. So wird einzig `array_linux.go` auf Linux-Systemen kompiliert. Alle anderen Dateien werden ignoriert.

## go clean

Dieser Befehl löscht alle Dateien, die vom Kompiler generiert wurden, einschließlich der unten gelisteten Dateien und Verzeichnisse.
	
	_obj/            // Altes Verzeichnis von object, als Überreste von Makefiles
	_test/           // Altes Verzeichnis von test, als Überreste von Makefiles
	_testmain.go     // Altes Verzeichnis von gotest, als Überreste von Makefiles
	test.out         // Altes Verzeichnis von test, als Überreste von Makefiles
	build.out        // Altes Verzeichnis von test, als Überreste von Makefiles
	*.[568ao]        // object Dateien, als Überreste von Makefiles

	DIR(.exe)        // Generiert von go build
	DIR.test(.exe)   // Generiert von go test -c
	MAINFILE(.exe)   // Generiert von go build MAINFILE.go

Überlicherweise nutze ich diese Befehle zum Säubern von Projekten, bevor ich diese auf GitHub hochlade. Sie sind nützlich für lokale Tests, aber nutzlos zur Versionskontrolle.

## go fmt und gofmt

Programmierer, die mit C/C++ arbeiten, sollten wissen, das Personen immer darüber debattieren, welcher Code-Stil besser sei: K&R-Stil oder ANSI-Stil. In Go gibt nur einen einzigen, welcher vorrausgesetzt wird. So müssen zum Beispiel offene, geschwungene Schleifen nur am Ende von Zeilen eingefügt werden und können nicht in einer eigenen stehen, da dies einen Kompilierungsfehler zur Folge hat! Jedoch musst Du Dir diese Regeln nicht merken. `go fmt` übernimmt diese Aufgabe für Dich. Führe einfach den Befehl `go fmt <Dateiname>.go` im Terminal aus. Persönlich nutze ich diesen Befehl selten, da die meisten IDEs diesen Befehl meist automatisch ausführen, sobald ich eine Datei speichere. Im nächsten Abschnitt werde ich näher auf IDEs eingehen.


`go fmt` ist nur ein Alias, welcher den Befehl `gofmt -l -w` bei Paketen anwendet, die in den Importpfaden genannt werden.

Wir nutzen üblicherweise `gofmt -w` statt `go fmt`. Somit wird Deine Quellcodedatei nicht umgeschrieben, nachdem sie formatiert wurde. `gofmt -w src` formatiert dagegen ein gesamtes Projekt.

## go get

Dieser Befehl ermöglicht es, Remote Packages herunterzuladen. Bisher untersützt es Bitbucket, GitHub, Google Code und Launchpad. Es geschehen zwei Dinge, nachdem wir den Befehl ausgeführt haben. Als erstes lädt Go den Quellcode herunter und führt danach `go install` aus. Bevor Du `go get` nutzt, solltest Du vorher die benötigten Versionskontrollsysteme herunterladen.

	BitBucket (Mercurial und Git)
	GitHub (Git)
	Google Code (Git, Mercurial, Subversion)
	Launchpad (Bazaar)
	

Um den Befehl auch nutzen zu können, musst Du diese Programme korrekt installieren. Vergiss nicht, `$PATH` zu setzen. Angemerkt sei, dass auch angepasste Domainnamen unterstützt werden. Nutze `go help remote`, um weitere Informationen zu erhalten.

## go install

Dieser Befehl kompiliert alle Pakete und generiert Dateien, die entweder nach `$GOPATH/pkg` oder `$GOPATH/bin` verschoben werden.

## go test

Dieser Befehl läd alle Dateinen, dessen Name `*_test.go` beinhaltet, generiert Dateien für Tests und gibt anschließend dessen Ergebnisse aus, die wie folgt aussehen können:

	ok   archive/tar   0.011s
	FAIL archive/zip   0.022s
	ok   compress/gzip 0.033s
	...
	
Es nutzt standardmäßig alle vorhanden Test-Dateien. Schaue unter `go help testflag` für Details.

## godoc

Viele Personen sagen, man brauche kein Dokumentationswerkzeug von Dritten, wenn man Go nutzt (obwohl ich mit [CHM](https://github.com/astaxie/godoc) selbst eins schrieb). Go besitzt ein mächtiges Wergzeug, um Dokumentationen nativ zu verwalten.

Aber wie können wir bestimmte Informationen über ein Paket einsehen? So möchtest Du zum Beispiel mehr über das `builtin` Paket wissen. Nutze hierfür `godoc builtin`. Mach es mit `godoc net/http` genauso, wenn Du mehr über das `http` Paket in Erfahrung bringen möchtest. Ist jedoch eine spezifische Funktion gefragt, benutze die `godoc fmt Printf` und `godoc -src fmt Printf` Befehle, um den Quellcode zu betrachten.

Führe den Befehl `godoc -http=:8080` aus und öffne dann `127.0.0.1:8080` in Deinem Browser. Nun solltest Du eine Deiner Sprache angepassten (lokalisierten) Version von golang.org sehen. So kannst Du nicht nur die Dokumentationen zu Paketen der Standardbibliothek ansehen, sondern auch aller Pakete, die unter `$GOPATH/pkg` gepspeichert sind. Dies ist großartig für Menschen, die von der Great Firewall of China im Internet eingeschränkt werden.

## Andere Befehle

Go verfügt über noch mehr Befehle, die wir nicht behandelt haben.


	go fix // Überführt alten Go Code von Go1 oder niedriger in eine neuere Version
	go version // Erhalte nähere Informationen über Deine Go Version
	go env // Zeigt die alle Umgebungsvariablen von Go
	go list // Listed alle installierten Pakete
	go run // Kompiliert temporäre Dateien und führt diese aus
	
Es gibt noch weitere Aspekte zu den Befehlen, über die ich nicht gesprochen habe. Du kannst `go help <command>` nutzen, um diese nachzulesen.

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [$GOPATH und Workspaces](01.2.md)
- Nächster Abschnitt: [Go Entwicklungswerkzeuge](01.4.md)


================================================
FILE: de/01.4.md
================================================
# Go Entwicklungswerkzeuge

In diesem Abschnitt werde ich Dir ein paar IDEs (***Integrated Developement Environments***) vorstellen, die Dir mit Funktionen wie intelligenter Codevervollständigung und automatischer Formatierung dabei helfen, effizienter zu programmieren. Alle Entwicklungsumgebungen sind plattformunabhängig, sodass die hier gezeigten Schritte nicht sehr verschieden seien sollten, auch wenn Du ein anderes Betriebssystem nutzt.

## LiteIDE

LiteIDE ist eine leichtgewichtige IDE, die open source ist und einzig für die Go Programmierung gedacht ist. Entwickelt wurde sie von visualfc.

![](images/1.4.liteide.png?raw=true)

Abbildung 1.4 Startansicht von LiteIDE

LiteIDEs Merkmale.

- Plattformunaghängigkeit
	- Windows
	- Linux
	- Mac OS
- Plattformübergreifende Kompilierung
	- Verwalte mehrere Kompilierungsumgebungen
	- Unterstützt die plattformübergreifende Kompilierung von Go-Code
- Standardisiertes Projektmanagement
	- Dokumentationsansicht basiert auf $GOPATH
	- Kompilierungsystem basiert auf $GOPATH
	- Index der API-Dokumentation basiert auf $GOPATH
- Go Quellcode Editor
	- Umschreibung von Code
	- Vollständige Unterstützung von gocode
	- Anzeige der Go Dokumentation und ein API Index
	- Hilfe zu Codefragmenten durch `F1`
	- Aufrufen von Funktionsdeklerationen durch `F2`
	- Gdb Unterstützung
	- Automatische Formatierung durch `gofmt`
- Anderes
	- Mehrsprachig
	- Plugin System
	- Texteditor Themes
	- Farbliche Syntaxhervorhebung basierend auf Kate
	- Intelligente Autovervollständigung basierend auf einer Volltext-Suche
	- Personalisierbare Tastenkürzel
	- Markdown Unterstützung
		- Echtzeit Vorschau
		- Personalisierbares CSS
		- Exportoptioen zu HTML und PDF
		- Konvertierung and Zusammenführung zu HTML und PDF
		
### LiteIDE Instalation

- Installiere LiteIDE
	- [Lade LiteIDE herunter](http://code.google.com/p/golangide)
	- [Quellcode](https://github.com/visualfc/liteide)
	
	Du musst Go zuerst installieren. Lade dafür die entsprechende Version für Dein Betriebssystem herunter. Entpacke das Archiv um es Programm direkt auszuführen.
- Installiere gocode

	Im nächsten Schritt muss gocode installiert werden, um die intelligente Autovervollständigung zu nutzen.
	
		go get -u github.com/nsf/gocode
		
- Kompilierungsumgebung

    Passe die Einstellungen von LiteIDE Deinen Betriebssystem entprechend an. Unter Windows mit der 64-Bit Variante von Go solltest Du win64 als Umgebung in der Symbolleiste auswählen. Dann wähle `opinion`, finde `LiteEnv` in der Liste auf der linken Seiten und öffne die Datei `win64.env` in der Liste zu Deiner Rechten.
	
		GOROOT=c:\go
		GOBIN=
		GOARCH=amd64
		GOOS=windows
		CGO_ENABLED=1

		PATH=%GOBIN%;%GOROOT%\bin;%PATH%
		。。。
	
    Ersetze `GOROOT=c:\go` mit Deinem Installationspfad von Go und speichere. Wenn Du MinGW64 nutzt, füge `C:\MinGW64\bin` der $PATH-Umgebungsvariable hinzu, um `cgo` starten zu können.

    Unter Linux mit einer 64-Bit Variante von Go, solltest Du linux64 als Umgebung in der Symbolleiste auswählen. Dann wähle `opinion`, finde `LiteEnv` in der Liste auf der linken Seiten und öffne die Datei `linux64.env` in der Liste zu Deiner Rechten.
	
		GOROOT=$HOME/go
		GOBIN=
		GOARCH=amd64
		GOOS=linux
		CGO_ENABLED=1

		PATH=$GOBIN:$GOROOT/bin:$PATH   
		。。。
		
	Ersetzte `GOROOT=$HOME/go` mit Deinem Installationspfad von Go und speichere. 
- $GOPATH
	$GOPATH ist ein Pfad, der eine Liste von allen Go-Projekten umfasst. Öffne die Kommandozeile (oder drücke `Ctrl+` in LiteIDE) und gib dann `go help gopath` ein, um mehr Details einzusehen. In LiteIDE ist es sehr einfach, den $GOPATH einzusehen und ihn zu verändern. Folge `View - Setup GOPATH`, um dies zu tun.
	
## Sublime Text

Nun möchte ich dir Sublime Text 2 (oder einfach Sublime) in Kombination mit den Plugins GoSublime, gocode und MarGo vorstellen. Lass mich erklären, warum.

- Intelligente Autovervollständigung

	![](images/1.4.sublime1.png?raw=true)
	
	Abbildung 1.5 Sublimes intelligente Autovervollständigung
- Automatische Formatierung des Quellcodes
- Unterstützung für Projektmanagement

	![](images/1.4.sublime2.png?raw=true)
	
	Abbildung 1.6 Projektmanagement in Sublime
	
- Farbliche Hervorhebung des Synax
- Es gibt eine Testversion ohne Einschränkungen der Funktionen. Es kann sein, dass Du nach einer Weile daran erinnert wirst, dass Du eine Lizenz kaufen sollest, aber Du kannst diese Meldung auch einfach ignorieren. Wenn Du aber glaubst, dass Sublime Dich produktiver macht und Du den Editor magst, solltest Du eine Lizenz kaufen, um die fortwährende Entwicklung zu unterstützen.

Zu aller erst solltest Du Dir eine für Dein Betriebssystem geeignete Version von [Sublime](http://www.sublimetext.com/) herunterladen.

1. Drücke ``Ctrl+` ``, öffne die Kommandozeile und füge folgenden Codesnippsel ein:

		import urllib2,os; pf='Package Control.sublime-package'; ipp=sublime.installed_packages_path(); os.makedirs(ipp) if not os.path.exists(ipp) else None; urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler())); open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read()); print 'Please restart Sublime Text to finish installation'
		
	Starte Sublime Text nach der Installation neu. Nun solltest Du im Menü unter dem Reiter `Preferences` die Option `Package Control` vorfinden.
	
	![](images/1.4.sublime3.png?raw=true)
	
	Abbildung 1.7 Die Paketverwaltung von Sublime

2. Zur Installation von GoSublime, SidebarEnhancements und Go Build, drücke `Ctrl+Shift+p` um die Paketverwaltung aufzurüfen und gib `pcip` (Kurzform für "Package Control: Install Package") ein.

	![](images/1.4.sublime4.png?raw=true)
	
	Abbildung 1.8 Installation von Paketen in Sublime
	
    Gib nun "GoSublime" ein, drücke auf OK, um das Paket zu installieren und wiederhole diese Schritte jeweils für SidebarEnhancements und Go Build. Starte den Editor nochmals neu, sobald alle Pakete installiert wurden.

3. Um sicher zu stellen, dass die Installation auch erfolgreich abgeschlossen wurde, starte Sublime und öffne die Datei `main.go`, um zu sehen, ob dessen Syntax farblich hervorgehoben wird. Gib `import` ein, um zu testen, ob die automatische Codevervollständigung nun funktioniert oder nicht.

	Wenn alles erfolgreich Verlaufen ist, können wir ja starten.
	
    Sollte dies nicht der Fall sein, solltest Du nochmal einen Blick auf die $PATH-Umgebungsvariable blicken. Öffne dazu die Kommandozeile und gib `gocode` ein. Sollte nichts ausgeführt werden, so wird $PATH wahrscheinlich nicht richtig konfiguriert worden sein.
	
## Vim

Vim ist ein populärer Texteditor unter Programmierern, welcher sich aus seinem minimalistischeren Vorgänger Vi hervorging. Zu seinen Funktionen gehören u.a. die intelligente Autovervollständung von Codesegmenten, Kompilierung und das Springen zu Fehlern im Quellcode.

![](images/1.4.vim.png?raw=true)
	
Abbildung 1.8 Vims intelligente Autovervollständigung für Go

1. Syntaxhervorhebung für Go

		cp -r $GOROOT/misc/vim/* ~/.vim/
		
2. Syntaxhervorhebung aktivieren 

		filetype plugin indent on
		syntax on
		
3. Installiere [gocode](https://github.com/nsf/gocode/)

		go get -u github.com/nsf/gocode
		
	gocode wird standardmäßig unter `$GOBIN` installiert.

4. Konfiguriere [gocode](https://github.com/nsf/gocode/)

		~ cd $GOPATH/src/github.com/nsf/gocode/vim
		~ ./update.bash
		~ gocode set propose-builtins true
		propose-builtins true
		~ gocode set lib-path "/home/border/gocode/pkg/linux_amd64"
		lib-path "/home/border/gocode/pkg/linux_amd64"
		~ gocode set
		propose-builtins true
		lib-path "/home/border/gocode/pkg/linux_amd64"
		
	Einige Worte zur Konfiguration von gocode:
	
	propose-builtins: aktiviert bzw. deaktiviert die Autovervollständigung; standardmäßig auf false gesetzt.
	lib-path: gocode sucht lediglich unter `$GOPATH/pkg/$GOOS_$GOARCH` und `$GOROOT/pkg/$GOOS_$GOARCH` nach Paketen. Mit dieser Einstellung können weitere Pfade hinzugefügt werden..

5. Glückwunsch! Tippe `:e main.go` ein und mache Deine ersten Schritte in Go!

## Emacs

Emacs wird auch als "Weapon of God" bezeichnet. Es handelt sich nicht nur um einen Editor, sondern vielmehr um eine mächtige IDE.

![](images/1.4.emacs.png?raw=true)

Abbildung 1.10 Emacs Hauptfenster als Go-Editor

1. Syntaxhervorhebung
	
		cp $GOROOT/misc/emacs/* ~/.emacs.d/
		
2. Installiere [gocode](https://github.com/nsf/gocode/)

		go get -u github.com/nsf/gocode
		
	gocode wird standardmäßig unter `$GOBIN` installiert.
3. Konfiguriere [gocode](https://github.com/nsf/gocode/)

		~ cd $GOPATH/src/github.com/nsf/gocode/vim
		~ ./update.bash
		~ gocode set propose-builtins true
		propose-builtins true
		~ gocode set lib-path "/home/border/gocode/pkg/linux_amd64"
		lib-path "/home/border/gocode/pkg/linux_amd64"
		~ gocode set
		propose-builtins true
		lib-path "/home/border/gocode/pkg/linux_amd64"
		
4. Installiere [Auto Completion](http://www.emacswiki.org/emacs/AutoComplete)
	
		~ make install DIR=$HOME/.emacs.d/auto-complete
	
	Konfiguriere die ~/.emacs-Datei
	
		;;auto-complete
		(require 'auto-complete-config)
		(add-to-list 'ac-dictionary-directories "~/.emacs.d/auto-complete/ac-dict")
		(ac-config-default)
		(local-set-key (kbd "M-/") 'semantic-complete-analyze-inline)
		(local-set-key "." 'semantic-complete-self-insert)
		(local-set-key ">" 'semantic-complete-self-insert)	
		
	Folge diesem [Link](http://www.emacswiki.org/emacs/AutoComplete) für weitere Informationen.

5. Konfiguriere .emacs

		;; golang mode
		(require 'go-mode-load)
		(require 'go-autocomplete)
		;; speedbar
		;; (speedbar 1)
		(speedbar-add-supported-extension ".go")
		(add-hook
		'go-mode-hook
		'(lambda ()
    		;; gocode
    		(auto-complete-mode 1)
    		(setq ac-sources '(ac-source-go))
    		;; Imenu & Speedbar
    		(setq imenu-generic-expression
        		'(("type" "^type *\\([^ \t\n\r\f]*\\)" 1)
        		("func" "^func *\\(.*\\) {" 1)))
    		(imenu-add-to-menubar "Index")
    		;; Outline mode
    		(make-local-variable 'outline-regexp)
    		(setq outline-regexp "//\\.\\|//[^\r\n\f][^\r\n\f]\\|pack\\|func\\|impo\\|cons\\|var.\\|type\\|\t\t*....")
    		(outline-minor-mode 1)
    		(local-set-key "\M-a" 'outline-previous-visible-heading)
    		(local-set-key "\M-e" 'outline-next-visible-heading)
    		;; Menu bar
    		(require 'easymenu)
    		(defconst go-hooked-menu
        		'("Go tools"
        		["Go run buffer" go t]
        		["Go reformat buffer" go-fmt-buffer t]
        		["Go check buffer" go-fix-buffer t]))
    		(easy-menu-define
        		go-added-menu
        		(current-local-map)
        		"Go tools"
        		go-hooked-menu)

    		;; Other
    		(setq show-trailing-whitespace t)
    		))
		;; helper function
		(defun go ()
    		"run current buffer"
    		(interactive)
    		(compile (concat "go run " (buffer-file-name))))

		;; helper function
		(defun go-fmt-buffer ()
    		"run gofmt on current buffer"
    		(interactive)
    		(if buffer-read-only
    		(progn
        		(ding)
        		(message "Buffer is read only"))
    		(let ((p (line-number-at-pos))
    		(filename (buffer-file-name))
    		(old-max-mini-window-height max-mini-window-height))
        		(show-all)
        		(if (get-buffer "*Go Reformat Errors*")
    		(progn
        		(delete-windows-on "*Go Reformat Errors*")
        		(kill-buffer "*Go Reformat Errors*")))
        		(setq max-mini-window-height 1)
        		(if (= 0 (shell-command-on-region (point-min) (point-max) "gofmt" "*Go Reformat Output*" nil "*Go Reformat Errors*" t))
    		(progn
        		(erase-buffer)
        		(insert-buffer-substring "*Go Reformat Output*")
        		(goto-char (point-min))
        		(forward-line (1- p)))
    		(with-current-buffer "*Go Reformat Errors*"
    		(progn
        		(goto-char (point-min))
        		(while (re-search-forward "<standard input>" nil t)
        		(replace-match filename))
        		(goto-char (point-min))
        		(compilation-mode))))
        		(setq max-mini-window-height old-max-mini-window-height)
        		(delete-windows-on "*Go Reformat Output*")
        		(kill-buffer "*Go Reformat Output*"))))
		;; helper function
		(defun go-fix-buffer ()
    		"run gofix on current buffer"
    		(interactive)
    		(show-all)
    		(shell-command-on-region (point-min) (point-max) "go tool fix -diff"))

6. Glückwunsch, Du hast es geschafft! Die Schnellzugriffsleiste (Speedbar) ist standardmäßig geschlossen - Entferne die Kommentarzeichen in der Zeile `;;(speedbar 1)`, um diese Funktion zu aktivieren, oder Du benutzt die Speedbar via `M-x speedbar`.

## Eclipse

Eclipse ist ebenfalls ein großartiges Entwicklungswerkzeug. Ich werde Dir zeigen, wie Du mit ihm Programme in Go schreiben kannst.

![](images/1.4.eclipse1.png?raw=true)

Abbildung 1.1 Eclipses Hauptfenster zum Programmieren Go 

1. Herunterladen und Installation von [Eclipse](http://www.eclipse.org/)
2. Lade [goclipse](https://code.google.com/p/goclipse/) herunter
	[http://code.google.com/p/goclipse/wiki/InstallationInstructions](http://code.google.com/p/goclipse/wiki/InstallationInstructions)
3. Lade gocode

	gocode auf Github.
	
		https://github.com/nsf/gocode
		
	Unter Windows musst Du git installiert haben. Wir nutzen überlicherweise [msysgit](https://code.google.com/p/msysgit/).
	
	Installiere gocode in der Kommandozeile
	
		go get -u github.com/nsf/gocode
		
	Du kannst die Installation mithilfe des Quellcodes selbst durchführen, wenn Du magst.
4. Installation von [MinGW](http://sourceforge.net/projects/mingw/files/MinGW/)
5. Konfiguration der Plugins.

	Windows->Preferences->Go
	
	(1).Einrichtung des Go-Compiler
	
	![](images/1.4.eclipse2.png?raw=true)
	
	Abbildung 1.12 Go-Einstellungen in Eclipse
	
	(2).Konfiguriere gocode(optional). Setze den Pfad zu gocode auf den Speicherort von gocode.exe.
	
	![](images/1.4.eclipse3.png?raw=true)
	
	Abbildung 1.13 gocode-Einstellungen
	
	(3).Konfiguriere gdb(optional). Setze den Pfad zu gdb auf den Speicherort von gdb.exe.
	
	![](images/1.4.eclipse4.png?raw=true)
	
	Abbildung 1.14 gdb-Einstellungen
6. Überprüfe, ob die Installation erfolgreich verlief

	Erstelle ein neues Go-Project und eine Datei hello.go wie folgt.
	
	![](images/1.4.eclipse5.png?raw=true)
	
	Abbildung 1.15 Erstelle ein neues Projekt und eine Datei
	
	Überprüfe die Installation wie folgt. (Die Befehle müssen in die Konsole von Eclipse eingegeben werden).
	
	![](images/1.4.eclipse6.png?raw=true)
	
	Abbildung 1.16 Teste ein Go-Programm in Eclipse

## IntelliJ IDEA

Programmierer, die bereits mit Java gearbeitet haben, sollte diese IDE bekannt sein. Es unterstützt die farbliche Hervorhebung von Go-Code und intelligente Autovervollständigung, welches durch ein Plugin erreicht wird.

1. Lade IDEA herunter. Es gibt keinen Unterschied zwischen der Ultimate- und Community-Edition.

	![](images/1.4.idea1.png?raw=true)
	
2. Installiere das Go-Plugin. Gehe zu `File - Setting - Plugins` und klicke dann auf `Browser repo`.

	![](images/1.4.idea3.png?raw=true)
	
3. Starte eine Suche mit `golang`, klicke doppelt auf `download and install` und warte, bis der Download abgeschlossen ist.

	![](images/1.4.idea4.png?raw=true)
	
	Klicke auf `Apply` und starte das Programm neu.

4. Nun kannst Du ein neues Go-Projekt erstellen.

	![](images/1.4.idea5.png?raw=true)
	
	Gib im nächsten Schritt den Speicherort Deines Go-SDK (***SDK steht für Software Developement Kit***) an - normalerweise handelt es sich hierbei um $GOROOT.
	
( ***Werfe einen Blick auf diesen [Blogartikel](http://wuwen.org/tips-about-using-intellij-idea-and-go/), welcher die Installation und Einrichtung von IntelliJ IDEA mit Go schrittweise erläutert.*** )

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Go Befehle](01.3.md)
- Nächster Abschnitt: [Zusammenfassung](01.5.md)


================================================
FILE: de/01.5.md
================================================
# 1.5 Zusammenfassung

In diesem Kapitel haben wir die Installation auf drei verschiedene Arten besprochen. Dies waren die manuelle Installation mit Hilfe des Quellcodes von Go, die offiziellen Ein-Klick-Installationen und durch Lösungen Dritter. Danach haben wir uns mit der Konfiguration der Go Entwicklungsumgebung auseinander gesetzt, welche hauptsächlich die Einrichtung Deines `$GOPATH` umfasst. Zudem habe ich Dir gezeigt, wie man Programme kompiliert und einsetzt. Des Weiteren hast Du die verschiedenen Terminal-Befehle zum Kompilieren, Installieren, Formatieren und Testen von Go kennengelernt. Zum Schluss hast Du Dir mächtige Entwicklungswerkzeuge wie LiteIDE, Sublime Text, Vim, GoLand, Emacs, Eclipse, IntelliJ IDEA u.a. zu Nutze gemacht. Suche Dir eines aus, um die Welt von Go zu erforschen.

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Go Entwicklungswerkzeuge](01.4.md)
- Nächstes Kapitel: [Grundlegendes Wissen zu Go](02.0.md)


================================================
FILE: de/02.0.md
================================================
# 2 Grundlegendes Wissen zu Go

Go ist eine kompilierte, systemnahe Programmiersprache und ist verwandt mit der C-Familie. Die Kompiliereung ist deutlich schneller als bei anderen C-Sprachen. Sie besitzt nur 25 Schlüsselwörter... also noch weniger als die 26 Buchstaben des deutschen Alphabets! Lass uns einen kurzen Blick auf diese Schlüsselwörter werfen, bevor wir anfangen.

    break    default      func    interface    select
    case     defer        go      map          struct
    chan     else         goto    package      switch
    const    fallthrough  if      range        type
    continue for          import  return       var

In diesem Kapitel werde ich Dir Grundlagen zur Programmierung in Go vermitteln. Du wirst sehen, wie prägnant die Sprache ist und wie schön sie gestaltet wurde. Das Programmieren in Go kann viel Spaß machen. Am Ende dieses Kapitels werden Dir die aufgelisteten Schlüsselwörter in ihrer Funktionsweise bekannt sein.   

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriges Kapitel: [Kapitel 1 Zusammenfassung](01.5.md)
- Nächster Abschnitt: ["Hallo Go"](02.1.md)

================================================
FILE: de/02.1.md
================================================
# 2.1 Hallo Go

Bevor wir unsere erste Anwendung in Go erstellen, müssen wir erst klein anfangen. Du kannst nicht erwarten, ein Haus bauen zu können, ohne die Grundlagen zu beherrschen. Deshalb werden wir den grundlegenden Syntax in diesem Abschnitt lernen, um ein einfaches Programm zu schreiben.

## Programm

In der Programmierung ist es in Klassiker, als erstes eine Anwendung zu schreiben, die einzig "Hallo Welt" ausgibt.

Bist Du bereit? Los geht's!

	package main
	
	import "fmt"
	
	func main() {
		fmt.Printf("Hallo Welt oder 你好,世界 oder καλημ ́ρα κóσμ oder こんにちは世界\n")
	}
	
Es sollte jetzt folgendes ausgegeben worden sein.

	Hallo Welt oder 你好,世界 oder καλημ ́ρα κóσμ oder こんにちは世界
	
## Erklärung

Eine Sache, die Du zu Beginn wissen solltest, ist, dass Go-Programme stets mit dem Schlüsselwort `package` anfangen.

`package <Paketname>` (in diesem Fall `package main`) sagt aus, dass diese Quellcodedatei zum Paket `main` gehört. Das Schlüsselwort `main` ist jedoch besonders, da es zu einer ausführbaren Binärdatei kompiliert wird. Normalerweise wird sonst ein Paket in der Dateiendung `.a` generiert.

Jedes ausführbare Programm hat nur ein einziges `main` Paket, dass die Funktion `main` beinhalten muss, die keine Argumente erhält und keine Werte zurückgibt.

Um `Hallo Welt...` auszugeben, haben wir eine Funktion mit dem Namen `Printf` genutzt. Diese Funktion stammt aus dem `fmt` Paket, welches wir in der dritten Zeile mit `import "fmt"` importiert haben.

Pakete werden ähnlich wie in Python behandelt, was ein paar Vorteile mit sich bring: Modularität (das Aufteilen eines Programms in kleinere Codesegmente, genannt Module) und Wiederverwendbarkeit (viele Module können auch in anderen Programmen genutzt werden). Das Konzept um Pakete hatten wir bereits aufgegriffen. Später werden wir auch eigene Pakete erstellen.

In der fünften Zeile haben wir das Schlüsselwort `func` verwendet, um die `main`-Funktion zu definieren. Der Rumpf bzw. Körper einer Funktion befindet sich zwischen `{}`, genau wie in C, C++ und Java.

Wie Du siehst, gibt es keine Argumente, die an die Funktion übergeben worden sind. Wir werden in wenigen Sekunden lernen, wie man diese in Funktionen nutzt. Du kannst auch Funktionen schreiben, die keinen oder beliebig viele Rückgabewerte haben.

In der sechsten Zeile rufen wir die Funktion `Printf` aus dem Paket `fmt` auf. Die geschieht über den Syntax `<Paketname>.<Funktionsname>`, also ganz im Stil von Python.

Wie in Kapitel 1 angemerkt, können sich der Name des Pakets und der Ordner, indem es sich das Paket befindet, durchaus verschieden sein. Hier stammt der `<Paketname>` vom Namen in `package <Paketname>` und nicht vom Ordnernamen ab. 

Du hast vielleicht mitbekommen, dass unser Beispiel oben viele Nicht-ASCII-Zeichen beinhaltet. Dies hat den Zweck zu zeigen, dass Go UTF-8 standardmäßig unterstützt. Du kannst jedes beliebige UTF-8 Zeichen in Deinen Programmen verwenden. 

## Zusammenfassung

Go nutzt `package` (wie Module in Python) zum Strukturieren von Programmen. Die Funktion `main.main()` (diese Funktion muss sich im `main`-Paket befinden) ist der Startpunkt von jedem Programm. Go unterstützt UTF-8-Zeichen, da einer ihrer Schöpfer zugleich UTF-8 mitentwickelt hat. Somit unterstützt Go von Beginn an mehrere Sprachen.  

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Grundlegendes Wissen zu Go](02.0.md)
- Nächster Abschnitt: [Grundlagen von Go](02.2.md)

================================================
FILE: de/02.2.md
================================================
# 2.2 Grundlagen von Go

In diesem Abschnit werden wir lernen, wie man Konstanten und Variablen mit grundlegenden Datentypen definiert, sowie ein paar weitere Fähigkeiten aus der Go-Programmierung.

## Variablen definieren

Es gibt syntaktisch viele Wege, eine Variable in Go zu definieren.

Das Schlüsselwort `var` ist die simpelste Form, eine Variable zu erstellen. Bedenke, dass in Go der Datentyp **hinter** dem Variablennamen steht.

	// Definiere eine Variable mit dem Namen “variableName” vom Typ "type"
	var variableName type

Definiere mehrere Variablen.

	// Definiere drei Variablen vom Typ "type"
	var vname1, vname2, vname3 type

Definiere eine Variable mit einem Startwert.

	// Definiere eine Variable mit dem Namen “variableName” vom Typ "type" und dem Wert "value"
	var variableName type = value

Definiere mehrere Variablen mit einem Startwert.

	/*
    Definiere drei Variablen vom Typ "type" und gib ihnen drei Startwerte.
    vname1 ist gleich v1, vname2 ist gleich  v2, vname3 ist gleich v3
	*/
	var vname1, vname2, vname3 type = v1, v2, v3

Findest Du es nicht auch ein wenig mühsehlig, Variablen auf diesem Weg zu definieren? Keine Sorge, denn das Team hinter Go hat auch so gedacht. Daher kannst Du Variablen Startwerte geben, ohne explizit den Datentyp zu definieren. Der Code würde dann so aussehen:

	/*
    Definiere drei Variablen vom Typ "type" und gib ihnen drei Ausgangswerte.
    vname1 ist gleich v1, vname2 ist gleich  v2, vname3 ist gleich v3
	*/
	var vname1, vname2, vname3 = v1, v2, v3

Schön, ich weiß das dies immer noch nicht einfach genug für Dich ist. Mal schauen, wie wir das lösen können.

	/*
	Definiere drei Variablen ohne den Typ "type", ohne das Schlüsselwort "var" und gib ihnen Startwerte.
    vname1 ist gleich v1,vname2 ist gleich v2,vname3 ist gleich v3
	*/
	vname1, vname2, vname3 := v1, v2, v3


So sieht es schon viel besser aus. Nutze `:=`, um `var` und `type` zu ersetzen. Es handelt sich hierbei um eine Kurzschreibweise. Aber warte, es gibt einen kleinen Haken: diese Form der Definition kann nur innerhalb von Fuktionen genutzt werden. Der Compiler wird sonst eine Fehlermeldung ausgeben, wenn Du es trotzdem außerhalb der `{}` einer Funktion versuchst. Daher nutzen wir meist das Schlüsselwort `var` um globale Variablen zu definieren oder die Funktion `var()`.

`_` (Unterstrich) ist ein besonderer Variablenname. Jeder übergebene Wert wird ignoriert. Übergeben wir zum Beispiel `35` an `b`, so verwerfen wir `34`. ( ***Dieses Beispiel soll nur die Funktionsweise aufzeigen. Es mag, wie in diesem Fall, nutzlos erscheinen, aber wir werden es oft gebrauchen, wenn wir Rückgabewerte von Funktionen erhalten.*** )

	_, b := 34, 35

Wenn Du Variablen in Deinem Programm definierst, aber keine Verwendung finden, wird der Compiler eine Fehlermeldung ausgeben. Versuche den unten stehenden Code zu kompilieren und schaue, was passiert.

	package main

	func main() {
	    var i int
	}

## Konstanten

Konstanten sind Werte, die während der Kompilierung festgelegt werden und während der Laufzeit nicht veränderbar sind. In Go kannst Du Konstanten als Wert Nummern, Booleans oder Strings geben.

Definiere eine Konstante wie folgt.

	const constantName = value
	// Du kannst auch den Datentyp hinzufügen, wenn nötig
	const Pi float32 = 3.1415926

Mehr Beispiele.

	const Pi = 3.1415926
	const i = 10000
	const MaxThread = 10
	const prefix = "astaxie_"

## Grundlegende Datentypen

### Boolean

In Go nutzen wir `bool`, um Booleans (Wahrheitswerte) auszudrücken, die entweder den Zustand `true` oder `false` annehmen können, wobei `false` der Standardwert ist. ( ***Du kannst übrigens Nummern zu Booleans und umgekehrt konvertieren!*** )

	// Beispielcode
	var isActive bool  // Globale Variable
	var enabled, disabled = true, false  // Der Datentyp wird ausgelassen
	func test() {
    	var available bool  // Lokale Variable
    	valid := false      // Kurzschreibweise einer Definition
    	available = true    // Eine Variable deklarieren
	}

### Numerische Datentypen

Der Datentyp Integer (ganze Zahlen) kann sowohl den positiven, als auch den negativen Zahlenraum umfassen, was durch ein Vorzeichen kenntlich gemacht wird. Go besitzt `int` und `uint`, welche den selben Wertebereich haben. Dessen Größe hängt aber vom Betriebssystem ab. Es werden 32-Bit unter 32-Bit Betriebssystemen verwendet und 64-Bit unter 64-Bit Betriebssystemen. Go umfasst außerdem Datentypen mit einer spezifischen Länge: `rune`, `int8`, `int16`, `int32`, `int64`, `byte`, `uint8`, `uint16`, `uint32` und `uint64`. Bedenke, dass `rune` ein Alias für `int32` ist und `byte` dem `uint8` gleicht.

Eine wichtige Sache, die Du wissen solltest, ist, dass Du verschiedene Datentypen nicht vermischen kannst, da es sonst zu Fehlern bei der Kompilierung kommt.

	var a int8

	var b int32

	c := a + b


Obwohl int32 einen größeren Wertebereich als int8 abdeckt, und beide vom Typ `int` sind, kannst Du sie nicht miteinander kombinieren. ( ***c wird hier der Typ `int` zugewiesen*** )

Floats (Gleitkommazahlen) haben entweder den Datentyp `float32` oder `float64`, aber es gibt keinen Datentyp namens `float`. `float64` wird standardmäßig verwendet, sollte die Kurzschreibweise für eine Variablendekleration genutzt werden.

War das schon alles? Nein! Go unterstützt auch komplexe Zahlen. `complex128` (bestehend aus 64-Bit für den realen Anteil und weiteren 64-Bit für den imaginären Teil) ist der Standarddatentyp. Solltest Du einen kleineren Wertebereich benötigen, kannst `complex64` als Datentyp verwenden (mit 32-Bit für den realen, und nochmals 32-Bit für den imaginären Teil). Die Schreibweise lautet `RE+IMi`, wo `RE` für den realen Teil steht, und `IM` den Imaginären Part repräsentiert. Das `i` am Ende ist die imaginäre Zahl. Hier ist ein Beispiel für eine komplexe Zahl.

	var c complex64 = 5+5i
	// Ausgabe: (5+5i)
	fmt.Printf("Der Wert ist: %v", c)

### Strings

Wir sprachen vorhin darüber, das Go eine native UTF-8 Unterstützung mit sich bringt. Strings (Zeichenketten) werden durch Anführungszeichen `""` gekennzeichet, oder durch Backticks (rückwärts geneigtes Hochkomma) ``` `` ```.

	// Beispielcode
	var frenchHello string  // Grundlegende Schreibweise zur Definition eines Strings
	var emptyString string = ""  // Definiert einen leeren String
	func test() {
    	no, yes, maybe := "no", "yes", "maybe"  // Kurzschreibweise
    	japaneseHello := "Ohaiou"
    	frenchHello = "Bonjour"  // Grundlegende Deklaration
	}

Es ist unmöglich, die Zeichen eines Strings anhand ihres Index zu verändern. Du wirst eine Fehlermeldung erhalten, solltest Du dies ausprobieren.

	var s string = "Hallo"
	s[0] = 'c'

Aber was ist, wenn ich wirklich nur ein Zeichen in einem String ändern möchte? Probieren wir es mit mit diesem Codebeispiel.

	s := "hello"
	c := []byte(s)  // Konvertiere den String zum Typ []byte
	c[0] = 'c'
	s2 := string(c)  // Wandle den Wert in eine String zurück
	fmt.Printf("%s\n", s2)


Nutze den `+` Operator, um zwei Strings zu verknüpfen.

	s := "Hallo"
	m := " Welt"
	a := s + m
	fmt.Printf("%s\n", a)


oder auch

	s := "Hallo"
	s = "c" + s[1:] // Du kannst die Werte mit Hilfe des Index nicht verändern, aber sie abfragen
	fmt.Printf("%s\n", s)


Was ist, wenn ein String über mehrere Zeilen verlaufen soll?

	m := `Hallo
    Welt`

`\`` wird die Zeichen in einem String escapen (d.h. mit `\` dessen Ausführung verhindern).

### Fehlermeldungen

Go besitzt mit `error` einen eigenen Datentyp, um mit Fehlermeldungen umzugehen. Zudem gibt es auch ein Paket mit dem Namen `errors`, um weitere Möglichkeiten bereitzustellen, Fehlermeldungen zu verarbeiten.

	err := errors.New("emit macho dwarf: elf header corrupted")
	if err != nil {
    	fmt.Print(err)
	}

### Grundeliegende Datenstrukturen

Die folgende Grafik enstammt dem Artikel [Datenstrukturen in Go](http://research.swtch.com/godata) (auf englisch) aus [Russ Coxs Blog](http://research.swtch.com/). Wie Du sehen kannst, nutzt Go Abschnitte des Arbeitsspeichers, um Daten zu speichern.

![](images/2.2.basic.png?raw=true)

Abbildung 2.1 Gos grundlegende Datenstrukturen

## Einige Fähigkeiten

### Gruppierte Definition

Wenn Du mehrere Konstanten und Variablen deklarieren oder Pakete importieren möchtest, kannst Du dies auch gruppiert durchführen.

Übliche Vorgehensweise.

	import "fmt"
	import "os"

	const i = 100
	const pi = 3.1415
	const prefix = "Go_"

	var i int
	var pi float32
	var prefix string

Gruppierter Ansatz.

	import(
    	"fmt"
    	"os"
	)

	const(
    	i = 100
    	pi = 3.1415
    	prefix = "Go_"
	)

	var(
    	i int
    	pi float32
    	prefix string
	)

Wird innerhalb von `constant()` einer Konstanten das Schlüsselwort `iota` als Wert zugewiesen, hat sie den Wert `0`. Werden den folgenden Konstanten keine expliziten Werte zugewiesen, wird der letzte zugeweise Wert von `iota` um 1 erhöht und der folgenden Konstante zugewiesen. Dieses Verhalten beleuchten wir im folgenden Absatz.

### Aufzählen mit iota

Go besitzt das Schlüselwort `iota`, um eine Aufzählung zu starten. Der Startwert ist `0` und wird jeweils um `1` erhöht.

	const(
    	x = iota  // x == 0
    	y = iota  // y == 1
    	z = iota  // z == 2
    	w  // Folgt dem Namen der Konstante keine Deklaration, so wird die zuletzt erfolgte verwendet. w = iota wird somit implizit auf iota gesetzt. Daher gilt w == 3. Folglich kannst Du  bei x und y "= iota" einfach auslassen.
	)

	const v = iota // Sobald iota erneut auf `const` trifft, wird erneut mit `0` gestartet, also gilt v = 0.

	const (
	  e, f, g = iota, iota, iota // e, f und g haben den selben Wert 0, da sie in der selben Zeile stehen.
	)

### Einige Regeln

Der Grund, warum Go so prägnant ist, liegt im vorhersehbaren Verhalten der Programmiersprache.

- Jede Variable, die mit einem großgeschriebenen Buchstaben anfängt, kann exportiert werden. Andernfalls ist sie privat.
- Die selbe Regel gilt auch für Funktionen und Konstanten. Schlüsselwörter wie `public` oder `private` existieren in Go nicht.

## Array, Slice, Map

### Array

Ein `array` ist eine Aneinanderreihung von Daten, die wie folgt definiert wird:

	var arr [n]Datentyp

wobei in `[n]Datentyp` das `n` die Länge des Arrays angibt. `Datentyp` ist selbsterklärend der Datentyp der Elemente (bzw. der aneinandergereihten Daten). Wie in anderen Programmiersprachen nutzen wir `[]`, um Daten im Array zu speichern oder um sie auszulesen.  

	var arr [10]int  // Ein Array vom Typ [10]int
	arr[0] = 42      // Der erste Index des Arrays ist 0
	arr[1] = 13      // Einem Element wird ein Wert zugewiesen
	fmt.Printf("Das erste Element ist %d\n", arr[0])   // Beim Auslesen des Wertes wird 42 zurückgegeben
	fmt.Printf("Das letzte Element ist %d\n", arr[9]) // Es gibt den Standardwert des 10. Elements zurück, was in diesem Fall 0 ist.

Da die Länge ein Teil des Array-Typs ist, sind `[3]int` und `[4]int` verschieden, sodass wir die Länge eines Arrays nicht ändern können. Nutzt Du Arrays als Argument in einer Funktion, dann wird eine Kopie des Arrays übergeben, statt einem Zeiger (bzw. ein Verweis) auf das Original. Möchtest Du stattdessen den Zeiger übergeben, dann musst Du einen `slice` verwenden. Darauf gehen wir aber später nochmals ein.

Es ist möglich, `:=` zu nutzen, um ein Array zu deklarieren.

	a := [3]int{1, 2, 3} // Deklariere ein Array vom Typ int mit drei Elementen
	b := [10]int{1, 2, 3} // Deklariere ein int-Array mit zehn Elementen, bei dem die ersten Drei einen Wert zugewiesen bekommen. Der Rest erhält den Standardwert 0.
	c := [...]int{4, 5, 6} // Nutze `…` statt der Längenangabe. Go wird die Länge dann selbst bestimmen.

Vielleicht möchtest Du auch Arrays als Element in einem Array nutzen. Schauen wir mal, wie das geht.

	// Deklariere ein zweidimensionales Array mit zwei Elementen, welche jeweils vier Elemente besitzen.
	doubleArray := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}}


	// Die Dekleration kann auch ein wenig kompakter geschrieben werden.
{% raw %}	easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}} {% endraw %}

Arrays sind grundlegende Datenstrukturen in Go.

![](images/2.2.array.png?raw=true)

Abbildung 2.2 Die Zuordnung in einem mehrdimensionalen Array

### Slice

In vielen Situationen ist ein Array als Datentyp keine gute Wahl, wenn wir während der Deklaration dessen Länge noch nicht wissen. Daher brauchen wir so etwas wie ein "dynamisches Array" mit einer variabler Länge. Diese werden in Go `slice` genannt.

`slice` ist nicht wirklich ein `dynamisches Array`. Es ist vielmehr ein Zeiger auf ein darunterliegendes `array` mit einer ähnlichen Deklaration, dass aber keine Länge benötigt.

	// Man deklariert ein Slice wie ein Array, lässt jedoch die Länge weg.
	var fslice []int

Nun deklarieren wir ein `slice` und vergeben Startwerte.

	slice := []byte {'a', 'b', 'c', 'd'}

`slice` kann existierende Slices oder Arrays verändern. `slice` nutzt `array[i:j]` zum "Herrausschneiden" von Elementen. `i` gibt den Index des Startpunkts an und kopiert alle Elemente bis zum Index `j`. Beachte, dass `array[j]` nicht in dem Ausschnitt enthalten ist, da das Slice eine Länge von `j-i` hat.

	// Deklariere ein Array mit der Länge 10 von vom Typ byte
	var ar = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}

	// Erstelle zwei Slices vom Typ []byte
	var a, b []byte

	// 'a' verweist auf die Elemente zwischen Index 3 und 5 im Array ar.
	a = ar[2:5]
	// 'a' besitzt nun die Elemente ar[2],ar[3] und ar[4]

	// 'b' ist ein weiterer Ausschnitt (Slice) vom Array ar
	b = ar[3:5]
	// 'b' besitzt nun die Elemente ar[3] und ar[4]

Beachte die Unterscheide bei der Deklaration von `slice` und `array`. Wir nutzen `[…]`, um Go die Länge automatisch herausfinden zu lassen, aber nutzen `[]` lediglich zur Deklaration von Slices.

Ihre zugrundeliegenden Datentypen.

![](images/2.2.slice.png?raw=true)

Abbildung 2.3 Der Zusammenhang zwischen Slices und Arrays

Slices haben bestimmte Anwendungsgebiete.

- Ein `slice` beginnt mit dem Index 0, `ar[:n]` gleicht `ar[0:n]`.
- Der zweite Index gibt die Länge vom Slice an, wenn er ausgelassen wird. `ar[n:]` gleicht `ar[n:len(ar)]`.
- Du kannst auch `ar[:]` nutzen, um einen gesamtes Array zu kopieren, wie in den ersten beiden Punkten erklärt.

Mehr Beispiele zu `slice`

	// Deklariere ein Array
	var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
	// Deklariere zwei Slices
	var aSlice, bSlice []byte

	// Einige gewöhnliche Anwendungsfälle
	aSlice = array[:3] // ist das Gleiche wie aSlice = array[0:3]. aSlice hat die Elemente a,b,c
	aSlice = array[5:] // ist das Gleiche wie aSlice = array[5:10]. aSlice hat die Elemente f,g,h,i,j
	aSlice = array[:]  // ist das Gleiche wie aSlice = array[0:10]. aSlice beinhaltet alle Elemente

	// Ein Slice vom Slice
	aSlice = array[3:7]  // aSlice hat die Elemente d,e,f,g,Anfang=4,Kapazität=7
	bSlice = aSlice[1:3] // bSlice beinhaltet aSlice[1], aSlice[2], also hat es die Elemente e,f
	bSlice = aSlice[:3]  // bSlice beinhaltet aSlice[0], aSlice[1], aSlice[2], also hat es die Elemente d,e,f
	bSlice = aSlice[0:5] // Der Slice ist nun länger, sodass bSlice d,e,f,g,h beinhaltet
	bSlice = aSlice[:]   // bSlice hat nun die gleiche Elemente wie aSlice, also d,e,f,g

`slice` ist ein Datentyp mit einem Zeiger, sodass Änderungen am Slice auch andere Variablen verändern, die wiederum selbt auf den Slice verweisen. Wie im oberigen Fall von `aSlice` und `bSlice`: veränderst Du den Wert eines Elements in `aSlice`, wird sich dieser auch im `bSlice` ändern.

`slice` ist ähnlich wie ein Struct und besteht aus drei Komponenten:

- Ein Zeiger, der auf den Beginn des `slice` bzw. zugrundeliegenden Array verweist.
- Die Länge definiert den Ausschnitt des zugrundeliegenden Arrays.
- Kapazität definiert die max. Größe des zugrundeliegenden Arrays.

		Array_a := [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
		Slice_a := Array_a[2:5]

Die zugrundeliegenden Datenstrukturen vom vorherigen Code sehen wie folgt aus:

![](images/2.2.slice2.png?raw=true)

Abbildung 2.4 Arrayelemente eines Slice

Es existieren eingebaute Funktionen, um mit Slices zu arbeiten.

- `len` gibt die Länge eines `slice` bzw. Ausschnitts zurück.
- `cap` gibt die max. Länge  (Kapazität) eines `slice` zurück.
- `append` erweitert den `slice` um ein oder mehrere Elemente, und gibt einen `slice` zurück.
- `copy` erstellt eine Kopie eines Slices, und gibt die Anzahl der kopierten Elemente zurück.

Achtung: `append` wird das Array, aus das `slice` verweist verändern, sowie andere Slices, die auf das selbe Array verweisen. Sollte de Kapazität des zugrundeliegenden Arrays nicht ausreichen (`(cap-len) == 0`), dann gibt `append` ein neues Array zurück. Dies hat aber keine Auswirkungen auf andere Slices, die auf das alte Array verwiesen.

### Map

`map` verhält sich wie ein Dictionary in Python. Nutze das Schema `map[SchlüsselTyp]WerteTyp`, um es zu deklarieren.

Schauen wir uns ein wenig Code an. Die 'set'- und 'get'-Werte in `map` sind der von `slice` sehr ähnlich. In einem Slice kann der Datentyp des Index nur ein `int` sein. In einer `map` kann es sich jedoch um einen `int`, `string` oder um jeden anderen Datentyp handeln. Du kannst auch `==` und `!=` verwenden, um Werte mit einander zu vergleichen.

	// Nutze 'string' als Datentyp für den Schlüssel, 'int' als Datentyp für den Wert und `make` zum Erstellen.
	var numbers map[string] int
	// Ein alternativer Weg zum Deklarieren
	nummern := make(map[string]int)
	nummern["eins"] = 1  // Weise ein Wert durch einen Schlüssel zu
	nummern["zehn"] = 10
	nummern["drei"] = 3

	fmt.Println("Die dritte Nummer lautet: ", nummern["drei"]) // Lese den Wert aus
	// Ausgabe: Die dritte Nummer lautet: 3

Einige Anmerkungen zur Nutzung von maps.

- `map` ist ungeordnet. Jedesmal, wenn Du eine `map` ausgeben willst, erhälst Du ein anderes Ergebnis. Dadurch ist es unmöglich, Werte über den `index` abzufragen. Nutze dafür den entsprechenden `Schlüssel`.
- `map` hat keine feste Länge. Dieser Datentyp ist wie `slice` lediglich ein Verweis.
- `len` funktioniert bei `map` auch. Es werden die Anzahl der `Schlüssel` zurückgegeben.
- Es ist ziemlich einfach, der Wert in einer `map` zu ändern.  Nutze `nummern["eins"]=11`, um den `Schlüssel` eins den Wert `11` zuzuweisen.

Du kannst das Schema `Schlüssel:Wert` nutzen, um eine `map` mit Startwerten zu erstellen. `map` hat auch eingebaute Funktionen, um die Existenz eines `key` zu überprüfen.

Benutze `delete`, um ein Element in `map` zu löschen.

	// Erstelle eine map
	bewertung := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
	// Map hat zwei Rückgabewerte. Der zweite Rückgabewert 'ok' wird, wenn der Schlüssel nicht existiert,aus false gesetzt. Andernfalls wird true zurückgegeben.
	csharpBewertung, ok := bewertung["C#"]
	if ok {
    	fmt.Println("C# ist in der map hat die Bewertung ", csharpBewertung)
	} else {
    fmt.Println("Es konnte keine Bewertung für C# in der map gefunden werden.")
	}

	delete(bewertung, "C")  // Lösche das Element mit dem Schlüssel "c"

Wie ich bereits sagte, ist `map` lediglich ein Verweis. Verweisen zwei `map`s auf die gleiche, zugrundeliegende Datenstruktur, wird eine Änderung Auswirkungen auf beide `map`s haben.

	m := make(map[string]string)
	m["Hallo"] = "Bonjour"
	m1 := m
	m1["Hallo"] = "Salut"  // Nun ist der Wert von m["hello"] Salut

### make, new

`make` reserviert Speicher für die eingebauten Datentypen, wie `map`, `slice`, und `channel`, wo hingegen `new` für selbstdefinierte Datentype (durch `type` definiert) Speicher zuweist.

`new(T)` ordnet dem Datentyp `T` Speicherplatz zu und initialisiert diesen mit den Standardwerten des jeweiligen Datentyps (z.B. `false` für einen `bool`). Anschließend wird die Adresse des Speicherortes in des Datentyps `*T` zurückgegeben. Nach der Definition von Go ist dies ein Zeiger, welcher auf die Standardwerte der Initilisierung von `T` verweist.

`new` gibt Zeiger als Wert zurück.

Die eingebaute Funktion `make(T, args)` hat einen anderen Zweck als `new(T)`. `make` kann für `slice`, `map`, und `channel` genutzt werden und gibt den Datentyp `T` mit seinem definierten Startwert zurück. Der Grund liegt darin, dass das ein Objekt vom zugrundeliegenden Datentyp erst erstellt wird, bevor auf diesen verwiesen werden kann. Dies ist bei diesen drei Datentypen der Fall. Zum Beispiel beinhaltet `slice` einen Zeiger, der auf das zugrundeliegende Array, die Länge und die Kapazität verweist. Vor der Initialisierung der Daten beinhaltet `slice` jedoch nur `nil`. Daher vergibt `make` den Datentypen `slice`, `map` und `channel` geeignetere Werte.

`make` gibt dabei die angesprochenen Standardwerte der entsprechenden Datentypen zurück (z.B. `false` für einen `bool`).

Die folgende Grafik verdeutlicht den Unterschied zwischen `new` und `make`.

![](images/2.2.makenew.png?raw=true)

Abbildung 2.5 Wie make und new Datenstrukturen Speicherplatz zuweisen

Standardwerte besitzen einen Wert. Dies sind die gebräuchlichsten Anwendungsfälle. Hier eine kleine Liste von Standardwerten.

	int     0
	int8    0
	int32   0
	int64   0
	uint    0x0
	rune    0 // rune ist ein Alias für int32
	byte    0x0 // byte ist ein Alias für uint8
	float32 0 // Die Größe beträgt 4 Byte
	float64 0 // Die Größe beträgt 8 Byte
	bool    false
	string  ""

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: ["Hallo Go"](02.1.md)
- Nächster Abschnitt: [Kontrollstrukturen und Funktionen](02.3.md)


================================================
FILE: de/02.3.md
================================================
# 2.3 Kontrollstrukturen und Funktionen

In diesem Kapite
werfen wir einen Blick auf Kontrollstrukturen und Funktionen in Go.

## Kontrollstrukturen

Die beste Erfindung in der Programmierung ist die Möglichkeit, den Ablauf einen Programms dynamisch verändern zu können. Um dies zu ermöglichen, kannst Du Kontrollstrukturen verwenden, um komplexe, logische Verknüpfungen darzustellen. Es gibt drei Arten, den Programmablauf zu ändern: Bedingungen, Schleifen, die eine Aufgabe mehrmals durchführen können und Sprungmarken.

### if

`if` ist das am weitverbreiteste Schlüsselwort in Deinen Programmen. Sollte eine Bedingung erfüllt sein, wird das Programm eine bestimmte Aufgabe ausführen. Wird die Bedingung nicht erfüllt, dann passiert etwas Anderes.

In Go braucht man keine runden Klammern für eine `if`-Bedingung nutzen.

    if x > 10 {
        fmt.Println("x ist größer als 10")
    } else {
        fmt.Println("x ist kleiner gleich 10")
    } 

Der nützlichste Aspekt in Bezug auf `if` ist, dass man vor der Überprüfung der Bedingung noch Startwerte vergeben kann. Die Variablen mit den Startwerten sind aber nur im `if`-Block selbst abrufbar.

    // Gebe x einen Startwert und überprüfe dann, ob x größer als 10 ist 
    if x := berechneEinenWert(); x > 10 {
        fmt.Println("x ist größer als 10")
    } else {
        fmt.Println("x ist kleiner als 10")
    }

    // Der folgende Code kann nicht kompiliert werden
    fmt.Println(x)

Benutze if-else für mehrere Bedingungen.

    if integer == 3 {
        fmt.Println("Der Integer ist gleich 3")
    } else if integer < 3 {
        fmt.Println("Der Integer ist kleiner als 3")
    } else {
        fmt.Println("Der Integer ist größer als 3")
    }

### goto


Go umfasst auch das `goto` Schlüsselwort, aber benutze es weise. `goto` verändert den Ablauf des Programms, indem es an einer vorher definierten Sprungmarke im selben Codeabschnitt weiterläuft.

    func meineFunktion() {
        i := 0
    Hier:   // Sprungmarken enden mit einem ":"
        fmt.Println(i)
        i++
        goto Hier   // Springe nun zur Sprungmarke "Hier"
    }

Es wird zwischen der Groß- und Kleinschreibung von Sprungmarken unterschieden. `Hier` ist nicht das Selbe wie `hier`.

### for

`for` ist die mächtigste Kontrollstruktur in Go. Sie kann Daten lesen und sie in jedem Durchgang verändern, ähnlich wie `while`.

    for Ausdruck1; Ausdruck2; Ausdruck3 {
        //...
    }

`Ausdruck1`, `Ausdruck2` und `Ausdruck3` sind alle Ausdrücke, aber bei `Ausdruck1` und `Ausdruck3` handelt es sich aber entweder um eine Deklaration von Variablen oder um Rückgabewerte von Funktionen. `Ausdruck2` ist dagegen eine zu erfüllende Bedingung . `Ausdruck1` wird nur einmal vor der Ausführung der Schleife verändert, aber `Ausdruck3` kann mit jedem Durchlauf verändert werden.

Aber Beispiele sagen mehr als tausend Worte.

    package main
    import "fmt"

    func main(){
        summe := 0;
        for index:=0; index < 10 ; index++ {
            summe += index
        }
        fmt.Println("summe hat den Wert ", summe)
    }
    // Ausgabe: summe hat den Wert 45

Manchmal müssen wir am Anfang mehrere Deklarationen vornehmen. Da Go für die Trennung der Variablen über kein `,` verfügt, können die Variablen nicht einzeln deklariert werden. Ein Ausweg bietet die parallele Deklaration: `i, j = i + 1, j - 1`.

Wenn nötig, können wir `Ausdruck1` und `Ausdruck3` auch einfach auslassen.

    summe := 1
    for ; summe < 1000;  {
        summe += summe
    }

Auch das `;` kann ausgelassen werden. Kommt es Dir bekannt vor? Denn ist das gleiche Verhalten wie bei `while`.

    summe := 1
    for summe < 1000 {
        summe += summe
    }

Es gibt mit `break` und `continue` zwei wichtige Schlüsselwörter bei der Verwendung von Schleifen. `break` wird zum "Ausbrechen" aus einer Schleife genutzt, während `continue` zum nächsten Durchlauf springt. Sollten verschachtelte Schleifen genutzt werden, dann kombiniere `break` mit einer Sprungmarke.

    for index := 10; index>0; index-- {
        if index == 5{
            break // oder continue
        }
        fmt.Println(index)
    }
    // break gibt 10、9、8、7、6 aus
    // continue gibt 10、9、8、7、6、4、3、2、1 aus

`for` kann auch die Elemente aus einem `slice` oder einer `map` lesen, wenn dies im Zusammenspiel mit `range` geschieht.

    for k, v := range map {
        fmt.Println("map's Schlüssel:",k)
        fmt.Println("map's Wert:",v)
    }

Go unterstützt die Rückgabe mehrerer Werte und gibt eine Fehlermeldung aus, wenn nicht genauso viele Variablen zum Speichern vorhanden sind. Solltest Du einen Wert nicht brauchen, kannst Du ihn mit `_` verwerfen. 

    for _, v := range map{
        fmt.Println("map's Wert:", v)
    }

### switch

Manchmal findest Du Dich in einer Situation vor, indem viele Bedingungen mit `if-else` geprüft werden müssen. Der Code kann dann schnell unleserlich und schwer anpassbar werden. Alternativ kannst Du Bedingungen auch mit `switch` prüfen. 

    switch Audruck {
    case Fall1:
        Eine Aufgabe
    case Fall3:
        Eine andere Aufgabe
    case Fall3:
        Eine andere Aufgabe
    default:
        Anderer Code
    }

Der Datentyp von `Fall1`, `Fall2` und `Fall3` muss der selbe sein. `switch` kann sehr flexible eingesetzt werden. Bedingungen müssen keine Konstanten sein und die einzelnen Fälle werden von oben nach unten geprüft, bis eine passender gefunden wurde. Sollte `switch` kein Ausdruck folgen, dann dann wird von einem `bool` ausgegangen und es wird der Code im Fall `true` ausgeführt.

    i := 10
    switch i {
    case 1:
        fmt.Println("i ist gleich 1")
    case 2, 3, 4:
        fmt.Println("i ist gleich 2, 3 oder 4")
    case 10:
        fmt.Println("i ist gleich 10")
    default:
        fmt.Println("ich weiß nur, dass i ein Integer ist")
    }

In der fünften Zeile nutzen wir gleich mehrere Fälle auf einmal. Außerdem brauchen wir nicht `break` am Ende jedes Falls einfügen, wie es in anderen Programmiersprachen üblich ist. Mit dem Schlüsselwort `fallthrough` kannst Du nach einem Treffer auch alle folgenden Fälle ausführen.

    integer := 6
    switch integer {
    case 4:
        fmt.Println("integer <= 4")
        fallthrough
    case 5:
        fmt.Println("integer <= 5")
        fallthrough
    case 6:
        fmt.Println("integer <= 6")
        fallthrough
    case 7:
        fmt.Println("integer <= 7")
        fallthrough
    case 8:
        fmt.Println("integer <= 8")
        fallthrough
    default:
        fmt.Println("Standardfall")
    }

Das Programm gibt folgende Informationen aus.

    integer <= 6
    integer <= 7
    integer <= 8
    Standardfall

## Funktionen

Nutze das Schlüsselwort `func`, um eine Funktion einzuleiten.

    func funcName(eingabe1 typ1, eingabe2 typ2) (ausgabe1 typ1, ausgabe2 typ2) {
        // Körper bzw. Rumpf der Funktion
        // Mehrere Werte werden zurückgegeben
        return wert1, wert2
    }

Dem gezeigten Beispiel können wir somit folgende Informationen entnehmen:

- Nutze das Schlüsselwort `func`, um die Funktion `funcName` zu erstellen.
- Funktionen können ein, mehrere oder kein Argument übergeben werden. Der Datentyp wird nach dem Argument angegeben und Argumente werden durch ein `,` getrennt.
- Funktionen können mehrere Werte zurückgeben.
- Es gibt zwei Rückgabewerte mit den Namen `ausgabe1` and `ausgabe2`. Du kannst Ihren Namen auch einfach auslassen und nur den Datentyp im Kopf angeben.
- Wenn es nur einen Rückgabewert gibt, kannst Du die Klammer um den Datentyp im Kopf weglassen.
- Wenn keine Daten zurückgegeben werden, kannst Du `return` einfach weglassen.
- Um Werte im Körper der Funktion zurückzugeben, musst Du `return` verwenden. 

Gucken wir uns mal ein Beispiel an, in dem wir den Größeren von zwei Werten bestimmen.

    package main
    import "fmt"

    // Gib den größeren Wert von a und b zurück
    func max(a, b int) int {
        if a > b {
            return a
        }
        return b
    }

    func main() {
        x := 3
        y := 4
        z := 5

        max_xy := max(x, y) // ruft die Funktion max(x, y) auf
        max_xz := max(x, z) // ruft die Funktion max(x, z) auf

        fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
        fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
        fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // rufe die Funktion hier auf
    }

Im oberen Beispiel übergeben wir jeweils zwei Argumente vom Typ `int` an die Funktion `max`. Da beide Argumente denn gleichen Datentyp besitzen, reicht es, wenn wir diesen nur einmal angeben. So kannst Du statt `a int, b int` einfach `a, b int` schreiben. Dies gilt auch für weitere Argumente. Wie Du sehen kannst, wird nur ein Wert von `max` zurückgegeben, sodass wir den Namen der Variable weglassen können. Dies wäre einfach die Kurzschreibweise. 

### Mehrere Rückgabewerte bei Funktionen

Die Möglichkeit, mehrere Werte zurückgeben zu können, ist ein Aspekt, in der Go der Programmiersprache C überlegen ist.

Schauen wir uns das folgende Beispiel an.

    package main
    import "fmt"

    // Gebe die Ergebnisse von A + B und A * B zurück
    func SummeUndProdukt(A, B int) (int, int) {
        return A+B, A*B
    }

    func main() {
        x := 3
        y := 4

        xPLUSy, xMALy := SummeUndProdukt(x, y)

        fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
        fmt.Printf("%d * %d = %d\n", x, y, xMALy)
    }

Das obere Beispiele gibt zwei namenlose Werte zurück. Aber Du kannst sie natürlich auch bennenen, wenn Du magst. Würden wir dies tun, müssten wir mit `return` nur dessen Namen zurückgeben, da die Variablen in der Funktion bereits automatisch initialisiert wurden. Bedenke, dass Funktionen mit einen großen Buchstaben anfangen müssen, wenn Du sie außerhalb eines Pakets verwenden möchtest. Es wäre auch zu empfehlen, die Rückgabewerte zu bennenen, da dies den Code verständlicher macht.   

    func SummeUndProdukt(A, B int) (addiert int, multipliziert int) {
        addiert = A+B
        multipliziert = A*B
        return
    }

### Variablen als Argumente

Go unterstützt auch Variablen als Argumente, was bedeutet, das einer Funktionen auch eine unbekannte Anzahl an Argumenten übergeben werden kann. 

    func myfunc(arg ...int) {}

`arg …int` besagt, dass diese Funktionen beliebig viele Argumente entgegennimmt. Beachte, dass alle Argumente vom Typ `int` sind. Im Funktionskörper wird `arg` zu einem `slice` vom Typ `int`.

    for _, n := range arg {
        fmt.Printf("Und die Nummer lautet: %d\n", n)
    }
    
### Werte und Zeiger übergeben

Wenn wir ein Argument einer aufgerufenen Funktion übergeben, dann bekommt diese meist eine Kopie des Arguments und kann somit das Original nicht beeinflussen.

Lass mich Dir ein Beispiel zeigen, um es zu beweisen.

    package main
    import "fmt"

    // Simple Funktion, die a um 1 erhöht
    func add1(a int) int {
        a = a+1  // Wir verändern den Wert von a 
        return a // Wir geben den Wert von a zurück
    }

    func main() {
        x := 3

        fmt.Println("x = ", x)  // Sollte "x = 3" ausgeben

        x1 := add1(x)  // Rufe add1(x) auf

        fmt.Println("x+1 = ", x1) // Sollte "x+1 = 4" ausgeben
        fmt.Println("x = ", x)    // Sollte "x = 3" ausgeben
    }

Siehst Du es? Selbst wenn wir der Funktion `add1` die Variable `x` als Argument übergeben, um sie um 1 zu erhöhen, so blieb `x` selbst unverändert

Der Grund dafür ist naheliegend: wenn wir `add1` aufrufen, übergeben wir ihr eine Kopie von `x`, und nicht `x` selbst.

Nun fragst Du dich bestimmt, wie ich das echte `x` einer Funktion übergeben kann.

Dafür müssen wir Zeiger verwenden. Wir wissen, das Variablen im Arbeitspeicher hinterlegt sind und sie eine Adresse für den Speicherort besitzen. Um einen Wert zu ändern, müssen wir auch die Adresse des Speicherorts wissen. Daher muss der Funktion `add1` diese Adresse von `x` bekannt sein, um diese ändern zu können. Hier übergeben wir `&x` der Funktion als Argument und ändern damit den Datentyp des Arguments in `*int`. Beachte, dass wir eine Kopie des Zeigers übergeben, und nicht des Wertes.

    package main
    import "fmt"

    // Simple Funktion, um a um 1 zu erhöhen
    func add1(a *int) int {
        *a = *a+1 // Wir verändern den Wert von a 
        return *a // Wir geben den Wert von a zurück
    }

    func main() {
        x := 3

        fmt.Println("x = ", x)  // Sollte "x = 3" ausgeben

        x1 := add1(&x)  // Rufe add1(&x) auf und übergebe die Adresse des Speicherortes von x

        fmt.Println("x+1 = ", x1) // Sollte "x+1 = 4" ausgeben
        fmt.Println("x = ", x)    // Sollte "x = 4" ausgeben
    }
    
Nun können wir den Wert von `x` in der Funktion ändern. Aber warum nutzen wir Zeiger? Was sind die Vorteile?

- Es erlaubt uns, mit mehreren Funktionen eine Variable direkt zu benutzen und zu verändern.
- Es braucht wenig Ressourcen, um die Speicheradresse (8 Bytes) zu übergeben. Kopien sind weniger effizient im Kontext von Zeit und Speichergröße.
- `string`, `slice` und `map` sind Referenztypen, die automatisch die Referenz (bzw. den Zeiger) der Funktion übergeben. (Achtung: Wenn Du die Länge eines `slice` ändern möchtest, musst Du den Zeiger explizit übergeben). 

### defer

Go besitzt mit `defer` ein weiteres nützliches Schlüsselwort. Du kannst `defer` mehrmals in einer Funktion nutzen. Sie werden in umgekehrter Reihenfolge am Ende einer Funktion ausgeführt. Im Fall, dass Dein Programm eine Datei öffnet, muss diese erst wieder geschlossen werden, bevor Fehler zurückgeben werden können. Schauen wir uns ein paar Beispiele an.

    func LesenSchreiben() bool {
        file.Open("Datei")
    // Mache etwas
        if FehlerX {
            file.Close()
            return false
        }

        if FehlerY {
            file.Close()
            return false
        }

        file.Close()
        return true
    }
    
Wir haben gesehen, dass hier der selbe Code öfters wiederhohlt wird. `defer` löst dieses Problem ziemlich elegant. Es hilft Dir nicht nur sauberen Code zu schreiben, sodern fördert auch noch dessen Lesbarkeit.

    func LesenSchreiben() bool {
        file.Open("Datei")
        defer file.Close()
        if FehlerX {
            return false
        }
        if FehlerY {
            return false
        }
        return true
    }
    
Wird `defer` mehr als einmal genutzt, werden sie in umgekehrter Reihenfolge ausgeführt. Das folgende Beispiel wird `4 3 2 1 0` ausgeben. 

    for i := 0; i < 5; i++ {
        defer fmt.Printf("%d ", i)
    }
    
### Funktionen als Werte und Datentypen

Funktionen sind auch Variablen in Go, die wir mit `type` definieren können. Funktionen mit der selben Signatur, also dem gleichen Aufbau, können als der selbe Datentyp betrachtet werden.

    type schreibeName func(eingabe1 eingabeTyp1 , eingabe2 eingabeTyp2 [, ...]) (ergebnis1 ergebnisTyp1 [, ...])

Was ist der Vorteil dieser Fähigkeit? Ganz einfach: wir können somit Funktionen als Werte übergeben.

    package main
    import "fmt"

    type testeInt func(int) bool // Definiere eine Funktion als Datentyp

    func istUngerade(integer int) bool {
        if integer%2 == 0 {
            return false
        }
        return true
    }

    func istGerade(integer int) bool {
        if integer%2 == 0 {
            return true
        }
        return false
    }

    // Übergebe die Funktion f als Argument an eine Andere Funktion

    func filter(slice []int, f testeInt) []int {
        var ergebnis []int
        for _, wert := range slice {
            if f(wert) {
                ergebnis = append(ergebnis, wert)
            }
        }
        return ergebnis
    }

    func main(){
        slice := []int {1, 2, 3, 4, 5, 7}
        fmt.Println("slice = ", slice)
        ungerade := filter(slice, istUngerade)    // Nutze die Funktion als Wert
        fmt.Println("Die ungeraden Elemente von slice lauten: ", ungerade)
        gerade := filter(slice, istGerade) 
        fmt.Println("Die geraden Elemente von slice lauten: ", gerade)
    }

Dies ist sehr nützlich, wenn wir Interfaces nutzen. Wie Du sehen kannst, wird `testeInt` eine Funktion als Argument übergeben, und die Rückgabewerte besitzen genau den gleichen Datentyp. Somit können wir komplexe Zusammenhänge in unseren Programen flexible warten und erweitern.

### Panic und Recover

Go besitzt keine `try-catch`-Struktur, wie es in Java der Fall ist. Statt eine Exception zu erstellen, nutzt Go `panic` und `recover`. Auch wenn `panic` sehr mächtig ist, solltest Du es nicht all zu oft benutzen.

`panic` ist eine eingebaute Funktion, um den normalen Ablauf des Programms zu unterbrechen und es in eine Art Panikmodus zu versetzen. Wenn die Funktion `F` `panic` aufruft, wird in ihr außer `defer` nichts weiter ausgeführt. Danach geht das Programm zum Ursprungsort des Fehlers zurück. Dies wird nicht geschlossen, ehe alle Funktionen einer `goroutine` `panic` zurückgeben. Einige Fehler erzeugen auch selbst einen Aufruf von `panic`, z.B. wenn der reservierte Speicherplatz eines Arrays nicht ausreicht.

`recover` ist ebenfalls eine eingebaute Fuktion, um `goroutinen` vom Panikmodus zu erlösen. Das Aufrufen von `recover` im Zusammenspiel mit `defer` ist sehr nützlich, da normale Funktionen nicht mehr ausgeführt werden, wenn sich das Programm erst einmal im Panikmodus befindet. Die Werte von `panic` werden so aufgefangen, wenn sich das Programm im Panikmodus befindet. Ansonsten wird `nil` zurückgegeben.

Das folgende Beispiel soll die Nutzung von `panic` verdeutlichen. 

    var benutzer = os.Getenv("BENUTZER")

    func init() {
        if benutzer == "" {
            panic("Kein Wert für $BENUTZER gefunden")
        }
    }
    
Das nächste Beispiel zeigt, wie der Status von `panic` aufgerufen werden kann.

    func erzeugePanic(f func()) (b bool) {
        defer func() {
            if x := recover(); x != nil {
                b = true
            }
        }()
        f() // Wenn 'f' 'panic' verursacht, wird versucht, dies mit 'recover' zu beheben 
        return
    }
    
### Die `main` und `init` Funktion

Go hat zwei besondere Funktionen mit dem Namen `main` und `init`, wobei `init` in jedem Paket aufgerufen werden kann und dies bei `main` nur im gleichnahmigen Paket möglich ist. Beide Funktionen besitzen weder Argumente, die übergeben werden können, noch geben sie Werte zurück. Es ist möglich, die `init`-Funktion innerhalb eines Pakets mehrmals aufzurufen, aber ich empfehle jedoch die Nutzung einer einzelnen, da es sonst unübersichtlich werden kann.

Go ruft `init()` und `main()` automatisch auf, sodass dies nicht manuell geschehen muss. Für jedes Paket ist die `init`-Funktion optional, jedoch ist die `main`-Funktion unter `package main` obligatorisch und kann lediglich ein einziges Mal genutzt werden.

Programme werden vom `main`-Paket aus gestarten. Wenn dieses Paket noch weitere Pakete importiert, geschieht dies einzig während der Kompilierung. Nach dem Importieren von Paketen werden zu erst dessen Konstanten und Variablen initialisiert, dann wird `init` aufgerufen usw. Nachdem alle Pakete erfolgreich initialisiert wurden, geschieht all dies im `main`-Paket. Die folgende Grafik illustriert diesen Ablauf.

![](images/2.3.init.png?raw=true)

Abbildung 2.6 Der Initialisierungsablauf eines Programms in Go

### import

Oftmals verwenden wir `import` in unseren Go-Programmen wie folgt.

    import(
        "fmt"
    )
    
Dann nutzen wir die Funktionen aus dem Paket wie im Beispiel:

    fmt.Println("Hallo Welt")

`fmt` stammt aus Gos Standardbibliothek, welche sich unter $GOROOT/pkg befindet. Go unterstützt Pakete von Dritten auf zwei Wege.

1. Relativer Pfad
    import `./model` // Importiert ein Paket aus dem selben Verzeichnis, jedoch empfehle ich diese Methode nicht.
2. Absoluter Pfad
    import `shorturl/model` // Lade das Paket mit dem Pfad "$GOPATH/pkg/shorturl/model"
    
Es gibt spezielle Operatoren beim Importieren von Paketen, die Anfänger oftmals verwirren.

1. Punkt Operator.
    
    Manchmal sieht man, wie Pakete auf diesem Weg importiert werden.
    
        import(
            . "fmt"
        )
    
    Der Punkt Operator bedeutet einfach, dass der Name des Paketes beim Aufruf von dessen Funktion weggelassen werden kann. So wird aus `fmt.Printf("Hallo Welt")` einfach `Printf("Hallo Welt")`.

2. Alias Operation.

    Dieser verändert den Namen des Paketes, denn wir beim Aufruf von Funktionen angeben müssen.
    
        import(
            f "fmt"
        )
        
    Aus `fmt.Printf("Hallo Welt")` wird dann `f.Printf("Hallo Welt")`.

3. `_` Operator.
    
    Dieser Operator ist ohne Erklärung ein wenig schwer zu erklären.
    
        import (
            "database/sql"
            _ "github.com/ziutek/mymysql/godrv"
        )
    
    Der `_` Operator bedeutet einfach nur, das wir das Paket importieren möchten und das dessen `init`-Funktion ausgeführt werden soll. Jedoch sind wir uns nicht sicher, ob wir die anderen Funktionen dieses Pakets überhaupt nutzen wollen.
    
## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Grundlagen von Go](02.2.md)
- Nächster Abschnitt: [Struct](02.4.md)


================================================
FILE: de/02.4.md
================================================
# 2.4 Struct

## Struct

Wie in anderen Programmiersprachen können wir auch in Go neue Datentypen erstellen, die als eine "Struktur" verknüpfte Eigenschaften oder Felder zusammenfasst. So können wir Beipielsweise einen neuen Datentyp `person` erschaffen, dessen Eingenschaften der Name und das Alter einer Person sind. Wir nennen diesen Datentyp `struct`.

    type person struct {
            name  string
            alter int
    }
    
Es sieht ziemlich einfach aus, ein `struct` zu definieren, nicht?

Es gibt insgesamt zwei Eigenschaften.

- `name` ist ein `string` und wird genutzt, um den Namen einer Person zu speichern.
- `alter` is vom Typ `int` und beinhaltet das Alter einer Person.

Schauen wir uns das einmal praktisch an.

    type person struct {
            name  string
            alter int
    }

    var P person  // p ist vom Typ person

    P.name = "Astaxie"  // Weise "Astaxie" der Eigenschaft 'name' von p zu
    P.alter = 25  // Weise 25 der Eigenschaft 'alter' von p zu
    fmt.Printf("Der Name der Person lautet %s\n", P.name)  // Rufe die Eigenschaft 'name' von p auf

Es gibt noch drei weitere Wege, ein Struct zu definieren.

- Weise Startwerte in der Reihenfolge der Eigenschaften zu.

        P := person{"Tom", 25}
    
- Oder nutze das Schema `Eigenschaft:Wert`, um ein Struct zu erstellen, ohne dabei auf die Reihenfolge achten zu müssen.

        P := person{alter:24, name:"Bob"}

- Definiere ein "anonymes" Struct und vergebe Startwerte

        P := struct{name string; alter int}{"Amy",18}
        
Schauen wir uns das vollständige Beispiel an.

    package main
    import "fmt"

    // Definiere einen neuen Datentyp
    type person struct {
        name string
        alter int
    }

    // Vergleiche das Alter von zwei Personen. Dann gibt die ältere Person und den Altersunterschied zurück
    // Structs werden als normaler Wert übergeben
    func Älter(p1, p2 person) (person, int) {
        if p1.alter>p2.alter {  
            return p1, p1.alter-p2.alter
        }
        return p2, p2.alter-p1.alter
    }

    func main() {
        var tom person

        // Initialisierung
        tom.name, tom.alter = "Tom", 18

        // Initialisiere zwei Werte nach dem Schema "Eigenschaft:Wert"
        bob := person{alter:25, name:"Bob"}

        // Initialisiere die Eigenschaft nach der Reihenfolge
        paul := person{"Paul", 43}

        tb_Älter, tb_diff := Älter(tom, bob)
        tp_Älter, tp_diff := Älter(tom, paul)
        bp_Älter, bp_diff := Älter(bob, paul)

        fmt.Printf("Von %s und %s ist %s um %d Jahre älter\n", tom.name, bob.name, tb_Älter.name, tb_diff)

        fmt.Printf("Von %s und %s ist %s um %d Jahre älter\n", tom.name, paul.name, tp_Älter.name, tp_diff)

        fmt.Printf("Von %s und %s ist %s um %d Jahre älter\n", bob.name, paul.name, bp_Älter.name, bp_diff)
    }
    
### Eigenschaften in Structs einbetten

Soeben habe ich Dir gezeigt, wie Du ein Struct mit Eigenschaften und Datentypen definieren kannst. Aber Go unterstützt auch Eigenschaften, die keinen Namen besitzen und nur dessen Datentyp angegeben wird. Wir bezeichnen diese als eingebettete Eigenschaften. 

Wenn die eingebette Eigenschaft ein weiteres Struct ist, dann all seine Eigenschaften in den Struct übertragen, in dem es eingebettet wurde.

Betrachten wir ein Beispiel.

    package main
    import "fmt"

    type Mensch struct {
        name string
        alter int
        gewicht int
    }

    type Student struct {
        Mensch  // Eingebettete Eigenschaft, d.h. Student besitzt alle Eigenschaften von Mensch.
        fachgebiet string
    }

    func main() {
        // Initialisierng eines Studenten
        mark := Student{Mensch{"Mark", 25, 120}, "Informatik"}

        // Eigenschaften aufrufen
        fmt.Println("Sein Name lautet ", mark.name)
        fmt.Println("Sein Alter ist ", mark.alter)
        fmt.Println("Er wiegt ", mark.gewicht)
        fmt.Println("Sein Fachgebiet ist ", mark.fachgebiet)
        // Eigenschaften verändern
        mark.fachgebiet = "Künstliche Intelligenz"
        fmt.Println("Mark hat sein Fachgebiet gewechselt")
        fmt.Println("Sein Fachgebiet lautet ", mark.fachgebiet)
        // Alter ändern
        fmt.Println("Mark wurde alt")
        mark.alter = 46
        fmt.Println("Sein Alter beträgt ", mark.alter, " Jahre")
        // Gewicht ändern
        fmt.Println("Mark ist kein Athlet mehr")
        mark.gewicht += 60
        fmt.Println("Er wiegt nun", mark.gewicht)
    }
    
![](images/2.4.student_struct.png?raw=true)

Abbildung 2.7 Einbettung von Mensch in Student

Wie Du siehst, können wir die Eigenschaften `alter` und `name` vom Typ Student genauso aufrufen, wie jene vom Typ Mensch. Genau so funktioniert das Einbetten. Ziemlich einfach, nicht wahr? Aber es gibt noch Kleinigkeit, die ich Dir zeigen möchte. Du kannst auch den Typ Mensch verwenden, um auf Eigenschaften von Student zurückzugreifen.

    mark.Mensch = Mensch{"Marcus", 55, 220}
    mark.Mensch.alter -= 1
    
In Go können alle Datenttypen eingebettet werden.

    package main
    import "fmt"

    type Fähigkeiten []string

    type Mensch struct {
        name string
        alter int
        gewicht int
    }

    type Student struct {
        Mensch  // Struct als eingebettete Eigenschaft
        Fähigkeiten // Slice vom Typ string als eingebettete Eigenschaft
        int    // Standard Datentyp als eingebettete Eigenschaft
        fachgebiet string
    }

    func main() {
        // Initialisiere Studentin Jane
        jane := Student{Mensch:Mensch{"Jane", 35, 100}, fachgebiet:"Biologie"}
        // Eigenschaften aufrufen
        fmt.Println("Ihr Name lautet ", jane.name)
        fmt.Println("Ihr Alter ist ", jane.alter)
        fmt.Println("Sie wiegt ", jane.gewicht)
        fmt.Println("Ihr Fachgebiet ist ", jane.fachgebiet)
        // Änderung des Wertes der Eigenschaft fähigkeit
        jane.Fähigkeiten = []string{"Anatomie"}
        fmt.Println("Sie besitzt folgende Fähigkeiten: ", jane.Fähigkeiten)
        fmt.Println("Sie hat zwei neue Fähigkeiten erworben ")
        jane.Fähigkeiten = append(jane.Fähigkeiten, "Physik", "Golang")
        fmt.Println("Sie besitzt nun folgende Fähigkeiten ", jane.Fähigkeiten)
        // Veränderung einer eingebetteten Eigenschaft
        jane.int = 3
        fmt.Println("Ihre bevorzugte Nummer lautet", jane.int)
    }
    
Im oberen Beispiel ist erkenntlich, dass alle Datentypen eingebettet werden und Funktionen auf ihre Werte zugreifen können.

Aber es gibt noch ein kleines Problem. Was geschieht, wenn Mensch die Eigenschaft `telefon` besitzt und Student eine Eigenschaft mit dem gleichen Namen besitzt?

Go nutzt einen einfachen Weg zur Unterscheidung. Um die Eigenschaft `telefon` von Student zu erhalten, nutzt Du weiterhein `Student.telefon`. Die gleichnahmige Eigenschaft von Mensch kannst Du erhalten, indem Du `Student.Mensch.telefon` verwendest. Wie Du siehst, muss einfach der eingebette Datentyp vorangestellt werden. Diese Fähigkeiten wird "überladen" genannt (im Englischen `overloading`).

    package main
    import "fmt"

    type Mensch struct {
        name string
        alter int
        telefon string  // Mensch hat die Eigenschaft telefon
    }

    type Mitarbeiter struct {
        Mensch  // Eingebetter Datentyp Mensch
        spezialisierung string
        telefon string  // Eigenschaft telefon in Mitarbeiter
    }

    func main() {
        Bob := Mitarbeiter{Mensch{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
        fmt.Println("Bobs berufliche Telefonnummer lautet ", Bob.telefon)
        // Greife auf Eigenschaft telefon in Mensch zu
        fmt.Println("Bobs private Telefonnummer lauet ", Bob.Mensch.telefon)
    }
    
## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Kontrollstrukturen und Funktionen](02.3.md)
- Nächster Abschnitt: [Objektorientiertes Programmieren](02.5.md)


================================================
FILE: de/02.5.md
================================================
# 2.5 Objektorientierte Programmierung

In den letzen beiden Abschnitten hatten wir uns mit Funktionen und Structs beschäftigt, aber hast Du jemals daran gedacht, Funktionen als Eigenschaft in einem Struct zu verwenden? In diesem Abschnitt werde ich Dir eine besondere Art von Funktionen vorstellen, die einen Reciever (engl. to recieve - empfangen) besitzen. Sie werden auch `Methoden` genannt.

## Methoden

Sagen wir, Du definierst einen Struct mit dem Namen "Rechteck" und möchtest die Fläche ausrechnen. Normalerweise würden wir folgenden Code verwenden, um dies zu bewerkstelligen.

    package main
    import "fmt"

    type Rechteck struct {
        breite, höhe float64
    }

    func Fläche(r Rechteck) float64 {
        return r.breite*r.höhe
    }

    func main() {
        r1 := Rechteck{12, 2}
        r2 := Rechteck{9, 4}
        fmt.Println("Fläche von r1: ", Fläche(r1))
        fmt.Println("Fläche von r2: ", Fläche(r2))
    }
    
Das obere Beispiel kann die Fläche eines Rechtecks ermitteln. Dafür haben wir die Funktion `Fläche()` verwendet, aber es ist keine Methode des Structs Rechteck (welche mit einer Klasse in klassischen objektorientierten Sprachen wären). Die Funktion und der Struct sind voneinander unabhängig.

Soweit ist dies noch kein Problem. Wenn Du aber den Flächeninhalt eines Kreies, Quadrahts, Fünfecks oder einer anderen Form berechnen musst, brauchst Du dafür Funktionen mit einem sehr ähnlichen Namen,

![](images/2.5.rect_func_without_receiver.png?raw=true)

Abbildung 2.8 Beziehung zwischen Funktionen und Structs

Offensichtlich ist dies nicht sehr praktisch. Auch sollte die Fläche eine Eigenschaft des Kreises oder Rechtecks sein.

Aus diesem Grund gibt es das Konzept der `Methoden`. Diese sind immer mit einem Datentyp verbunden. Sie haben den selben Syntax wie normale Funktionen, jedoch besitzen sie einen weiteren Parameter nach dem Schlüsselwort `func`, den `Reciever`.

Im selben Beispiel würde mit `Rechteck.Fläche()` die Methode des Structs Rechteck aufgerufen. Somit gehören `länge`, `breite` und `Fläche()` zum Struct.

Wie Rob Pike sagte:

    "A method is a function with an implicit first argument, called a receiver."
    
    "Eine Methode ist eine Funktion mit einem ersten, impliziten Argument, welches Reciever genannt wird."

Syntax einer Methode.

    func (r RecieverTyp) funcName(Parameter) (Ergebnis)
    
Lass uns das Beispiel von vorhin umschreiben.

    package main
    import (
        "fmt"
        "math"
    )

    type Rechteck struct {
        breite, höhe float64
    }

    type Kreis struct {
        radius float64
    }

    func (r Rechteck) fläche() float64 {
        return r.breite*r.höhe
    }

    func (c Kreis) fläche() float64 {
        return c.radius * c.radius * math.Pi
    }

    func main() {
        r1 := Rechteck{12, 2}
        r2 := Rechteck{9, 4}
        c1 := Kreis{10}
        c2 := Kreis{25}

        fmt.Println("Fläche von r1 ist: ", r1.fläche())
        fmt.Println("Fläche von r2 ist: ", r2.fläche())
        fmt.Println("Fläche von c1 ist: ", c1.fläche())
        fmt.Println("Fläche von c2 ist: ", c2.fläche())
    }
    
Anmerkungen zu der Nutzung von Methoden.

- Beide Methoden haben den selben Namen, gehören jedoch verschiedenen Recievern an.
- Methoden können auf die Eigenschaften des Recievers zugreifen.
- Nutze `.`, um Methoden wie Eigenschaften aufzurufen.

![](images/2.5.shapes_func_with_receiver_cp.png?raw=true)

Abbildung 2.9 Die Methoden sind in jedem Struct verschieden

Im oberen Beispiel ist die Methode `Fläche()` für Rechteck und Kreis zugänglich, sodass sie zwei verschiedene Reciever besitzt.

Bei der Nutzung von Methoden werden dieser Kopien der Werte eines Structs übergeben. `Fläche()` bekommt also nicht einen Zeiger zum Original übergeben, sondern nur eine Kopie dessen. Somit kann das Orginal nicht verändert werden. Ein `*` vor dem Reciver übergibt dageben den Zeiger und erlaubt damit auch Zugriff auf das Original.

Können Reciever nur in Verbindung mit Structs genutzt werden? Natürlich nicht. Jeder Datentyp kann als Reciever fungieren. Dies wird Dir vielleicht bei selbstdefinierten Datentypen etwas komisch vorkommen, aber mit den Structs haben wir das Selbe gemacht - einen eigenen Datentypen erstellt.

Das Folgende Schema kann genutzt werden, um einen neuen Datentypen zu definieren.

    type Name Datentyp
    
Beispiele für selbstdefinierte Datentypen:

    type alter int

    type geld float32

    type monate map[string]int

    m := monate {
        "Januar":31,
        "Februar":28,
        ...
        "Dezember":31,
    }
    
Ich hoffe, dass Du die Definition eigener Datentypen jetzt verstanden hast. Es ist `typedef` aus C sehr ähnlich. Im oberen Beispiel ersetzen wir `int` einfach durch `alter`.

Kommen wir zurück zu unseren `Methoden`.

Du kannst soviele Datentypen und dazugehörige Methoden erstellen, wie Du willst.

    package main
    import "fmt"

    const(
        WEISS = iota
        SCHWARZ
        BLAU
        ROT
        GELB
    )

    type Farbe byte

    type Box struct {
        breite, höhe, tiefe float64
        farbe Farbe
    }

    type BoxListe []Box // Ein Slice mit Elementen vom Typ Box

    func (b Box) Volumen() float64 {
        return b.breite * b.höhe * b.tiefe
    }

    func (b *Box) SetzeFarbe(c Farbe) {
        b.farbe = c
    }

    func (bl BoxListe) HöchsteFarbe() Farbe {
        v := 0.00
        k := Farbe(WEISS)
        for _, b := range bl {
            if b.Volumen() > v {
                v = b.Volumen()
                k = b.farbe
            }
        }
        return k
    }

    func (bl BoxListe) MaleAlleSchwarzAn() {
        for i, _ := range bl {
            bl[i].SetzeFarbe(SCHWARZ)
        }
    }

    func (c Farbe) String() string {
        strings := []string {"WEISS", "SCHWARZ", "BLAU", "ROT", "GELB"}
        return strings[c]
    }

    func main() {
        boxes := BoxListe {
            Box{4, 4, 4, ROT},
            Box{10, 10, 1, GELB},
            Box{1, 1, 20, SCHWARZ},
            Box{10, 10, 1, BLAU},
            Box{10, 30, 1, WEISS},
            Box{20, 20, 20, GELB},
        }

        fmt.Printf("Wir haben %d Boxen in unserer Liste\n", len(boxes))
        fmt.Println("Das Volumen der Ersten beträgt ", boxes[0].Volumen(), "cm³")
        fmt.Println("Die Farbe der letzen Box ist",boxes[len(boxes)-1].farbe.String())
        fmt.Println("Die größte Box ist ", boxes.HöchsteFarbe().String())

        fmt.Println("Malen wir sie alle schwarz an")
        boxes.MaleAlleSchwarzAn()
        fmt.Println("Die Farbe der zweiten Box lautet ", boxes[1].farbe.String())

        fmt.Println("Offensichtlich ist die größte Box ", boxes.HöchsteFarbe().String())
    }
    
Wir hatten ein paar Konstanten und selbstdefinierte Datentypen erstellt.

- Nutze `Farbe` als Alias für `byte`.
- Wir definierten den Struct `Box` mit den Eigenschaften breite, länge, tiefe und farbe.
- Wir definierten einen Slice `BoxListe` mit Elementen vom Typ `Box`.

Dann haben wir Methoden für unsere selbsterstellten Datentypen hinzugefügt.

- Volumen() nutzt Box als Reciever und gibt das Volumen einer Box.
- SetzeFarbe(c Farbe) ändert die Farbe einer Box.
- GrößteFarbe() gibt die Box mit dem größten Volumen zurück.
- MaleAlleSchwarzAn() setzt die Farbe aller Boxen auf schwarz.
- String() benutzt Farbe als Reciever und gibt den Farbnamen als String zurück.

Ist es nicht einfacher, Wörter zum Beschreiben unserer Anforderungen zu benutzen? Oftmals definieren wir unsere Anforderungen schon vor dem Programmieren.

### Zeiger als Reciever

Werfen wir einen näheren Blick auf die Methode `SetzeFarbe()`. Ihr Reciever ist der Zeiger mit dem Verweis zu einer Box. Warum benutzen wir hier einen Zeiger? Wie bereits erwähnt, erhälst Du mit `*Box` Zugriff auf das Original und kannst es somit ändern. Nützten wir keinen Zeiger, so hätte die Methode nur eine Kopie des Wertes übergeben bekommen.

Wenn wir einen Reciever als ersten Parameter einer Methode sehen, dürfte ihr Zweck leicht zu verstehen sein.

Du fragst Dich bestimmt, warum wir nicht einfach `(*b).Farbe=c` verwenden, statt `b.Color=c` in der `SetzeFarbe()` Methode. Beide Wege sind OK und Go weiß die erste Zuweisung zu interpretieren. Findest Du Go nun nicht auch faszinierend?

Des Weiteren fragst Du dich vielleicht auch, warum wir nicht `(&bl[i]).SetzeFarbe(BLACK)` in `MaleAlleSchwarzAn()` nutzen, so wie es in `SetzeFarbe()` der Fall ist. Nochmals, beide Varianten sind OK und Go weiß damit umzugehen. 

### Vererbung von Methoden

Wir haben die Vererbung bzw. das Einbetten von Eigengeschaften bereits im letzen Abschnitt kennengelernt. Ähnlich funktioniert auch das Einbetten von Methoden. Wenn ein Struct eigene Methoden hat und es in ein weiteres Struct eingebettet wird, so werden die Methoden wie die Eigenschaften mit eingebettet, also vererbt.

    package main
    import "fmt"

    type Mensch struct {
        name string
        alter int
        telefon string
    }

    type Student struct {
        Mensch // Eingebetter Struct als Eigenschaft ohne Namen
        schule string
    }

    type Mitarbeiter struct {
        Mensch 
        unternehmen string
    }

    // Definiere eine Methode für Mensch
    func (h *Mensch) SagHallo() {
        fmt.Printf("Hallo, ich bin %s. Du erreichst mich unter %s\n", h.name, h.telefon)
    }

    func main() {
        mark := Student{Mensch{"Mark", 25, "222-222-YYYY"}, "MIT"}
        sam := Mitarbeiter{Mensch{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}

        mark.SagHallo()
        sam.SagHallo()
    }

### Das Überladen von Methoden

Wenn wir für Mitarbeiter eine eigene Methode `SagHallo()` erstellen wollen, wird die Methode `SagHallo()` von Mensch durch die von Mitarbeiter überladen.

    package main
    import "fmt"

    type Mensch struct {
        name string
        alter int
        telefon string
    }

    type Student struct {
        Mensch 
        schule string
    }

    type Mitarbeiter struct {
        Mensch 
        unternehmen string
    }

    func (h *Mensch) SagHallo() {
        fmt.Printf("Hallo, ich bin %s und Du erreicht mich unter %s\n", h.name, h.telefon)
    }

    func (e *Mitarbeiter) SagHallo() {
        fmt.Printf("Hallo, ich bin %s, arbeite bei %s. Du erreicht mich unter %s\n", e.name,
            e.unternehmen, e.telefon) // Du kannst die Argumente auch auf zwei Zeilen verteilen.
    }

    func main() {
        mark := Student{Mensch{"Mark", 25, "222-222-YYYY"}, "MIT"}
        sam := Mitarbeiter{Mensch{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}

        mark.SagHallo()
        sam.SagHallo()
    }

Nun bist Du bereit, Dein eigenes, objektorientiers Programm zu schreiben. Auch Methoden unterliegen der Regel, dass die Groß- und Kleinschreibung des ersten Buchstaben über die Sichtbarkeit (öffentlich oder privat) entscheidet. 

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Struct](02.4.md)
- Nächster Abschnitt: [Interface](02.6.md)


================================================
FILE: de/02.6.md
================================================
# 2.6 Interfaces

## Interface

Eines der besten Sprachmerkmale von Go sind Interfaces. Nach dem Lesen dieses Abschnitts wirst Du über dessen Implementation staunen. 

### Was ist ein Interface

Kurz gesagt, ein Interface dient der Zusammenfassung von Funktionen, die durch ihren ähnlichen Aufbau eine Beziehung zueinander haben.

Wie im Beispiel aus dem letzten Abschnitt haben Student und Mitarbeiter hier beide die Methode `SagHallo()`, welche sich ähnlich, aber nicht gleich verhalten.

Machen wir uns wieder an die Arbeit, indem wir beiden Structs die Methode `Singen()` hinzufügen. Zudem erweitern wir Student um die Methode `GeldLeihen()` und Mitarbeiter um die Methode `GehaltAusgeben()`.

Nun besitzt Student die drei Methoden `SagHallo()`, `Singen()` und `GeldLeihen()` und Mitarbeiter `SagHallo()`, `Singen()` sowie `GehaltAusgeben()`. 

Diese Kombination von Methoden wird Interface genannt und umfasst sowohl Student als auch Mitarbeiter. Somit besitzen beide Datentypen die Interfaces `SagHallo()` und `Singen()`. Jedoch implementieren beide Datentypen keine gemeinsames Interfaces für `GeldLeihen()` und `GehaltAusgeben()`, da diese Methoden nicht für beide Structs definiert wurden.

### Interface als Datentyp

Ein Interface definiert eine Liste von Methoden. Besitzt ein Datentyp alle Methoden, die das Interface definiert, so umfasst das Interface diesen Datentypen. Schauen wir uns ein Beispiel zur Verdeutlichung an.

	type Mensch struct {
		name    string
		alter   int
		telefon string
	}

	type Student struct {
		Mensch
		schule string
		kredit float32
	}

	type Mitarbeiter struct {
		Mensch
		unternehmen string
		geld        float32
	}

	func (m *Mensch) SagHallo() {
		fmt.Printf("Hallo, ich bin %s und Du erreichst mich unter %s\n", m.name, m.telefon)
	}

	func (m *Mensch) Singen(liedtext string) {
		fmt.Println("La la, la la la, la la la la la...", liedtext)
	}

	func (m *Mensch) SichBetrinken(bierkrug string) {
		fmt.Println("schluck schluck schluck...", bierkrug)
	}

	// Mitarbeiter "überlädt" SagHallo
	func (m *Mitarbeiter) SagHallo() {
		fmt.Printf("Hallo, ich bin %s und arbeite bei %s. Ruf mich unter der Nummer %s an\n", m.name,
			m.unternehmen, m.telefon) // Du kannst die Argumente auch auf zwei Zweilen aufteilen.
	}

	func (s *Student) GeldLeihen(betrag float32) {
		s.kredit += betrag // (immer und immer wieder...)
	}

	func (m *Mitarbeiter) GehaltAusgeben(betrag float32) {
		m.geld -= betrag // Einen Vodka bitte!!! Bring mich durch den Tag!
	}

	// Das Interface definieren
	type Männer interface {
		SagHallo()
		Singe(liedtext string)
		SichBetrinken(bierkrug string)
	}

	type JungerMann interface {
		SagHallo()
		Singe(liedtext string)
		GeldLeihen(betrag float32)
	}

	type Greis interface {
		SagHallo()
		Singe(liedtext string)
		GeldAusgeben(betrag float32)
	}

Wir wissen, dass ein Interface von jedem Datentypen implementiert werden und ein Datentyp viele Interfaces umfassen kann.

Zudem implementiert jeder Datentyp das leere Interface `interface{}`, da es keine Methoden definiert und alle Datentypen von Beginn an keine Methoden besitzen.

### Interface als Datentyp

Welche Arten von Werten können mit einem Interface verknüpft werden? Wen wir eine Variable vom Typ Interface definieren, dann kann jeder Datentyp, der das Interface implementiert, der Variable zugewiesen werden.

Es ist wie im oberen Beispiel. Erstellen wir eine Variable "m" mit dem Interface Männer, kann jeder Student, Mensch oder Mitarbeiter "m" zugewiesen werden. So könnten wir ein Slice mit dem Interface Männer jeden Datentyp hinzufügen, der ebenfalls das Interface Männer implementiert. Bedenke aber, dass sich das Verhalten von Slices ändert, wenn dies Elemente eines Interface statt eines Datentypes verwendet.

	package main
	
	import "fmt"
	
	type Mensch struct {
		name    string
		alter   int
		telefon string
	}
	
	type Student struct {
		Mensch
		schule string
		geld   float32
	}
	
	type Mitarbeiter struct {
		Mensch
		unternehmen string
		geld        float32
	}
	
	func (m Mensch) SagHallo() {
		fmt.Printf("Hallo, ich bin %s und Du erreicht mich unter %s\n", m.name, m.telefon)
	}
	
	func (m Mensch) Singe(liedtext string) {
		fmt.Println("La la la la...", liedtext)
	}
	
	func (m Mitarbeiter) SagHallo() {
		fmt.Printf("Hallo, ich bin %s und arbeite bei %s. Rufe mich unter der Nummer %s an\n", m.name,
			m.unternehmen, m.telefon) // Du kannst die Argumente auch auf zwei Zweilen aufteilen.
	}
	
	// Das Interface Männer wird von Mensch, Student und Mitarbeiter implementiert
	type Männer interface {
		SagHallo()
		Singe(liedtext string)
	}
	
	func main() {
		mike := Student{Mensch{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
		paul := Student{Mensch{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
		sam := Mitarbeiter{Mensch{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
		tom := Mitarbeiter{Mensch{"Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000}
	
		// Definiere i vom Typ Interface Männer
		var i Männer
	
		// i kann Studenten zugewiesen bekommen
		i = mike
		fmt.Println("Das ist Mike, ein Student:")
		i.SagHallo()
		i.Singe("November rain")
	
		// i kann auch Mitarbeiter zugewiesen bekommen
		i = tom
		fmt.Println("Das ist Tom, ein Mitarbeiter:")
		i.SagHallo()
		i.Singe("Born to be wild")
	
		// Slice mit Männern
		fmt.Println("Nutzen wir einen Slice vom Typ Männer und schauen, was passiert")
		x := make([]Männer, 3)
		// Alle drei Variablen haben verschiedene Datentypen, implentieren aber das selbe Interface
		x[0], x[1], x[2] = paul, sam, mike
	
		for _, wert := range x {
			wert.SagHallo()
		}
	}

	
Ein Interface ist eine Ansammlung von abstrakten Methoden, das jeder Datentypen implementieren kann, die noch nicht Teil des Interfaces sind. Daher kann es sich nicht selbst implemetieren

### Leeres Interface

Ein leeres Interfaces umfasst keine Methoden, sodass alle Datentypen dieses Interface implementieren. Dies ist sehr nützlich, wenn wir irgendwann alle Datentypen speichern möchten. Es ist void* aus C sehr ähnlich.

	// Definition eines leeren Interfaces
	var a interface{}
	var i int = 5
	s := "Hallo Welt"
	// a kann jeder Datentyp zugewiesen werden
	a = i
	a = s

Wenn eine Funktion ein leeres Interface als Argumenttyp verwendet, wird jeder Datentyp akzeptiert. Gleiches gilt für den Rückgabewert einer Funktion.

### Ein Interface als Methodenargument

Jede Variable kann mit einem Interface genutzt werden. Aber wie können wir diese Eigenschaft nutzen, um einen beliebigen Datentyp einer Funktion zu übergeben?

Zum Beispiel nutzen wir `fmt.Println` sehr oft, aber hast Du jemals gemerkt, dass jeder Datentyp verwendet werden kann? Werfen wir mal einen Blick auf den open-source Code von `fmt`. Wir sehen die folgende Definition der Funktion.

	type Stringer interface {
    		String() string
	}
	
Dies bedeutet, dass jeder Datentyp, der das Interface Stringer implementiert, `fmt.Println` übergeben werden kann. Beweisen wir es.

	package main

	import (
		"fmt"
		"strconv"
	)

	type Mensch struct {
		name    string
		alter   int
		telefon string
	}

	// Mensch implementiert fmt.Stringer
	func (m Mensch) String() string {
		return "Name:" + m.name + ", Alter:" + strconv.Itoa(m.alter) + " Jahre, Kontakt:" + m.telefon
	}

	func main() {
		Bob := Mensch{"Bob", 39, "000-7777-XXX"}
		fmt.Println("Dieser Mensch ist: ", Bob)
	}

	
Werfen wir nochmal einen Blick auf das Beispiel mit den Boxen von vorhin. Du wirst feststellen, dass der Datentyp Farbe ebenfalls das Interface Stringer definiert, sodass wir die Ausgabe formatieren können. Würden wir dies nicht tun, nutzt `fmt.Println()` die Standardformatierung.

	fmt.Println("Die größte Box ist", boxen.HöchsteFarbe().String())
	fmt.Println("Die größte Box ist", boxen.HöchsteFarbe())
	

Achtung: Wenn Du das Interface `error` implementierst, wird `fmt` `error()` ausrufen, sodass Du ab hier Stringer noch nicht definieren brauchst.

### Datentyp eines Interfaces bestimmen

Wir wissen, dass einer Variable jeder Datentyp zugewiesen werden kann, der ein Interface mit dem originalen Datentypen teilt. Nun stellt sich die Frage, wie wir den genauen Datentypen einer Variable bestimmen können. Hierfür gibt es zwei Wege, die ich Dir zeigen möchte.

- Überprüfung nach dem Komma-ok-Muster

Der in Go übliche Syntax lautet `value, ok := element.(T)`. Er überprüft, ob eine Variable vom erwarteten Datentypen ist. "value" ist der Wert der Variable,"ok" ist vom Typ Boolean, "element" ist eine Interfacevariable und T der zu überprüfende Datentyp.

Wenn das Element dem erwarteten Datentypen entspricht, wird ok auf true gesetzt. Anderfalls ist er false.

Veranschaulichen wir dies anhand eines Beispiels.

	package main
	
	import (
		"fmt"
		"strconv"
	)
	
	type Element interface{}
	type Liste []Element
	
	type Person struct {
		name   string
		alter  int
	}
	
	func (p Person) String() string {
		return "(Name: " + p.name + " - Alter: 	" + strconv.Itoa(p.alter) + " Jahre)"
	}
	
	func main() {
		liste := make(Liste, 3)
		liste[0] = 1       // ein Integer
		liste[1] = "Hallo" // ein String
		liste[2] = Person{"Dennis", 70}
	
		for index, element := range liste {
			if value, ok := element.(int); ok {
				fmt.Printf("liste[%d] ist ein Integer mit dem Wert %d\n", index, value)
			} else if value, ok := element.(string); ok {
				fmt.Printf("liste[%d] ist ein String mit dem Wert %s\n", index, value)
			} else if value, ok := element.(Person); ok {
				fmt.Printf("liste[%d] ist eine Person mit dem Wert %s\n", index, value)
			} else {
				fmt.Printf("liste[%d] hat einen anderen Datentyp\n", index)
			}
		}
	}

Dieses Muster ist sehr einfach anzuwenden, aber wenn wir viele Datentypen zu bestimmen haben, sollten wir besser `switch` benutzen.

- Überprüfung mit switch

Machen wir von `switch` gebrauch und schreiben unser Beispiel um.
	
	package main
	
	import (
		"fmt"
		"strconv"
	)
	
	type Element interface{}
	type Liste []Element
	
	type Person struct {
		name   string
		alter  int
	}
	
	func (p Person) String() string {
		return "(Name: " + p.name + " - Alter: " + strconv.Itoa(p.alter) + " Jahre)"
	}
	
	func main() {
		liste := make(Liste, 3)
		liste[0] = 1       // Ein Integer
		liste[1] = "Hello" // Ein String
		liste[2] = Person{"Dennis", 70}
	
		for index, element := range liste {
			switch value := element.(type) {
			case int:
				fmt.Printf("liste[%d] ein Integer mit dem Wert %d\n", index, value)
			case string:
				fmt.Printf("liste[%d] ist ein String mit dem Wert %s\n", index, value)
			case Person:
				fmt.Printf("liste[%d] ist eine Person mit dem Wert %s\n", index, value)
			default:
				fmt.Println("liste[%d] hat einen anderen Datentyp", index)
			}
		}
	}


Eine Sache, die Du bedenken solltest, ist, dass `element.(type)` nur in Kombination mit `switch` genutzt werden kann. Andernfalls musst Du auf das Komma-ok-Muster zurückgreifen.	

### Eingebettete Interfaces

Eine der schönsten Eigenschaften von Go ist dessen eingebaute und vorrausschauende Syntax, etwa namenlose Eigentschaften in Structs. Nicht überraschend können wir dies ebenfalls mit Interfaces tun, die `eingebettete Interfaces` genannt werden. Auch hier gelten die selben Regeln wie bei namenlosen Eigenschaften. Anders ausgedrückt: wenn ein Interface ein anderes Interface einbettet, werden auch alle Methoden mit übernommen.  

Im Quellcode des Pakets `container/heap` lässt sich folgende Definition finden:

	type Interface interface {
	    	sort.Interface      // Eingetettetes sort.Interface
	    	Push(x interface{}) // Eine Push Methode, um Objekte im Heap zu speichern
	    	Pop() interface{}   // Eine Pop Methode, um Elemente aus dem heap zu löschen
	}

Wie wir sehen können, handelt es sich bei `sort.Interface` um ein eingebettes Interface. Es beinhaltet neben `Push()` und `Pop()` die folgenden drei Methoden implizit. 

	type Interface interface {
	    	// Len gibt die Anzahl der Objekte in der Datenstruktur an.
	    	Len() int
	    	// Less gibt in Form eines Boolean an, ob i mit j getauscht werden sollte
	    	Less(i, j int) bool
	    	// Swap vertauscht die Elemente i und j.
	    	Swap(i, j int)
	}
	
Ein weiteres Beispiel ist `io.ReadWriter` aus dem Paket `io`.

	// io.ReadWriter
	type ReadWriter interface {
    		Reader
    		Writer
	}
	
### Reflexion

Reflexion in Go wird genutzt, um Informationen während der Laufzeit zu bestimmen. Wir nutzen dafür das `reflect` Paket. Der offizelle [Artikel](http://golang.org/doc/articles/laws_of_reflection.html) erklärt die Funktionsweise von `reflect` in Go.

Die Nutzung von `reflect` umfasst drei Schritte. Als Erstes müssen wir ein Interface in `reflect`-Datentypen umwandeln (entweder in reflect.Type oder reflect.Value, aber dies ist Situationsabhängig).

	t := reflect.TypeOf(i)    // Speichert den Datentyp von i in t und erlaubt den Zugriff auf alle Elemente
	v := reflect.ValueOf(i)   // Erhalte den aktuellen Wert von i. Nutze v um den Wert zu ändern
	

Danach können wir die reflektierten Datentypen konvertieren, um ihre Werte zu erhalten.

	var x float64 = 3.4
	v := reflect.ValueOf(x)
	fmt.Println("Datentyp:", v.Type())
	fmt.Println("Die Variante ist float64:", v.Kind() == reflect.Float64)
	fmt.Println("Wert:", v.Float())
	

Wollen wir schließlich den Wert eines reflektierten Datentypen ändern, müssen wir ihn dynamisch machen. Wie vorhin angesprochen, gibt es einen Unterschied, wenn wir einen Wert als Kopie oder dessen Zeiger übergeben. Das untere Beispiel ist nicht kompilierbar.

	var x float64 = 3.4
	v := reflect.ValueOf(x)
	v.SetFloat(7.1)
	
Stattdessen müssen wir den folgenden Code verwenden, um die Werte der reflektierten Datentypen zu ändern.

	var x float64 = 3.4
	p := reflect.ValueOf(&x)
	v := p.Elem()
	v.SetFloat(7.1)

Nun kennen wir die Grundlagen der Reflexion. Es erfordert jedoch noch ein wenig Übung, um sich mit diesem Konzept vertraut zu machen.
	
## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Objektorientierte Programmierung](02.5.md)
- Nächster Abschnitt: [Nebenläufigkeit](02.7.md)


================================================
FILE: de/02.7.md
================================================
# 2.7 Nebenläufigkeit

Es wird behauptet, Go sei das C des 21. Jahrhunderts. Ich glaube, dafür gibt es zwei Gründe: erstens, Go ist eine simple Programmiersprache; zweitens: Nebenläufigkeit (Concurrency im Englischen) ist ein heißes Thema in der heutigen Welt und Go unterstützt die Eigenschaft als ein zentraler Aspekt der Sprache.

## Goroutinen
 
Goroutinen und Nebenläufigkeit sind zwei wichtige Komponenten im Design von Go. Sie ähneln Threads, funktionieren aber auf eine andere Weise. Ein dutzend Goroutinen haben vielleicht nur fünf oder sechs zugrundeliegende Threads. Des Weiteren unterstützt Go vollständig das Teilen von Speicherressourcen zwischen den Goroutinen. Eine Goroutine nimmt gewöhnlicherweise etwa 4 bis 5 KB Speicher ein. Daher ist es nicht schwer, tausende von Goroutinen auf einem einzelnen Computer zu nutzen. Goroutinen sind weniger ressourcenhungrig, effizienter und geeigneter als Systemthreads.

Goroutinen laufen im Thread Manager während der Laufzeit von Go. Wir nutzen das Schlüsselwort `go`, um eine neue Goroutine zu erstellen, wobei es sich eigentlich um eine interne Funktion von Go handelt ( ***main() ist ebenfalls eine Goroutine*** ).

    go Hallo(a, b, c)
    
Schauen wir uns ein Beispiel an.

    package main

    import (
        "fmt"
        "runtime"
    )

    func sag(s string) {
        for i := 0; i < 5; i++ {
            runtime.Gosched()
            fmt.Println(s)
        }
    }

    func main() {
        go sag("Welt") // Erzeugt eine neue Goroutine
        sag("Hallo")   // Aktuelle Goroutine
    }

Ausgabe:

    Hallo
    Welt
    Hallo
    Welt
    Hallo
    Welt
    Hallo
    Welt
    Hallo
    
Wie es scheint, ist es sehr einfach, Nebenläufigkeit in Go durch das Schlüsselwort `go` zu nutzen. Im oberen Beispiel teilen sich beide Goroutinen den selben Speicher. Aber es wäre besser, diesem Rat folge zu leisten: Nutze keine geteilten Daten zur Kommunikation, sondern kommuniziere die geteilten Daten.

`runtime.Gosched()` bedeutet, das die CPU andere Goroutinen ausführen und nach einiger Zeit an den Ausgangspunkt zurückkehren soll.

Das Steuerungsprogramm nutzt einen Thread, um alle Goroutinen auszuführen. Das bedeutet, dass einzig dort Nebenläufigkeit implementiert wird. Möchtest Du mehr Rechnenkerne im Prozessor nutzen, um die Vorteile paralleler Berechnungen einzubringen, musst Du `runtime.GOMAXPROCS(n)` aufrufen, um die Anzahl der Rechenkerne festzulegen. Gilt `n<1`, verändert sich nichts. Es könnte sein, dass diese Funktion in Zukunft entfernt wird. Für weitere Informationen zum verteilten Rechnen und Nebenläufigkeit findest Du in diesem [Artikel](http://concur.rspace.googlecode.com/hg/talk/concur.html#landing-slide).

## Channels

Goroutinen werden im selben Adressraum des Arbeitsspeichers ausgeführt, sodass Du in den Goroutinen die genutzen Ressourcen synchronisieren musst, wenn diese geteilt werden sollen. Aber wie kommuniziere ich zwischen verschiedenen Goroutinen? Hierfür nutzt Go einen sehr guten Mechanismus mit dem Namen `channel`. `channel` ist wie eine bidirektionale Übertragungsleitung (Pipe) in Unix-Shells: nutze `channel` um Daten zu senden und zu empfangen. Der einzige Datentyp, der in Kombination mit diesen Datenkanälen genutzt werden kann, ist der Typ `channel` und das Schlüsselwort `chan`. Beachte, dass Du `make` brauchst, um einen neuen `channel` zu erstellen.

    ci := make(chan int)
    cs := make(chan string)
    cf := make(chan interface{})
    
`channel` nutzt den Operator `<-`, um Daten zu senden und zu empfangen.

    ch <- v    // Sende v an den Kanal ch.
    v := <-ch  // Empfange Daten von ch und weise sie v zu
    
Schauen wir uns weitere Beispiele an.

    package main

    import "fmt"

    func summe(a []int, c chan int) {
        gesamt := 0
        for _, v := range a {
        gesamt += v
        }
        c <- gesamt  // Sende gesamt an c
    }

    func main() {
        a := []int{7, 2, 8, -9, 4, 0}

        c := make(chan int)
        go summe(a[:len(a)/2], c)
        go summe(a[len(a)/2:], c)
        x, y := <-c, <-c  // Empfange Daten von c

        fmt.Println(x, y, x + y)
    }
    

Das Senden und Empfangen von Daten durch die Datenkanäle wird standardmäßig gestoppt, um die Goroutinen einfach synchron zu halten. Mit dem Blocken meine ich, dass eine Goroutine nicht weiter ausgeführt wird, sobald keine Daten mehr von einem `channel` empfangen werden (z.B. `value := <-ch`) und andere Goroutinen keine weiteren Daten über den entsprechenden Kanal senden. Anderseits stoppt die sendende Goroutine solange, bis alle Daten (z.B. `ch<-5`)über den Kanal empfangen wurden.

## Gepufferte Channels

Eben habe ich die nicht-gepuffter Datenkanäle vorgestellt. Go unterstützt aber auch gepufferte Channel, die mehr als ein Element speichern können, z.B. `ch := make(chan bool, 4)`. Hier wurde ein Channel mit der Kapazität von vier Booleans erstellt. Mit diesem Datenkanal sind wir in der Lage, vier Elemente zu senden, ohne das die Goroutine stoppt. Dies passiert aber bei dem Versuch, ein fünftes Element zu versenden, ohne das es von einer Goroutine empfangen wird. 

    ch := make(chan type, n)

    n == 0 ! nicht-gepuffert(stoppt)
    n > 0 ! gepuffert(nicht gestoppt, sobald n Elemente im Kanal sind)
    
Experimentiere mit dem folgenden Code auf Deinem Computer und verändere die Werte.
    
    package main

    import "fmt"

    func main() {
        c := make(chan int, 2)  // Setze 2 auf 1 und Du erzeugst einen Laufzeitfehler. Aber 3 ist OK.
        c <- 1
        c <- 2
        fmt.Println(<-c)
        fmt.Println(<-c)
    }
    
## Range und Close

Wir können `range` in gepufferten Kanlen genauso nutzen, wie mit Slices und Maps.

    package main

    import (
        "fmt"
    )

    func fibonacci(n int, c chan int) {
        x, y := 1, 1
        for i := 0; i < n; i++ {
            c <- x
            x, y = y, x + y
        }
        close(c)
    }

    func main() {
        c := make(chan int, 10)
        go fibonacci(cap(c), c)
        for i := range c {
            fmt.Println(i)
        }
    }
    
`for i := range c` wird nicht eher mit dem Lesen von Daten aus dem Channel aufhören, ehe dieser geschlossen ist. Wir nutzen das Schlüsselwort `close`, um den Datenkanal im oberen Beispiel zu schließen. Es ist unmöglich, Daten über einen geschlossenen Channel zu senden oder zu empfangen. Mit `v, ok := <-ch` kannst Du den Status eines Kanals überprüfen. Wird `ok` auf false gesetzt, bedeutet dies, dass sich keine weiteren Daten im Channel befinden und er geschlossen wurde.

Denke aber immer daran, die Datenkanäle auf seiten der Datenproduzenten zu schließen und nicht bei den Empfängern der Daten. Andernfalls kann es passieren, dass sich Dein Programm in den Panikmodus versetzt.

Ein weiterer Aspekt, den wir nicht unterschlagen sollten, ist, dass Du Channels nicht wie Dateien behandeln solltest. Du brauchst sie nicht andauernd schließen, sondern erst, wenn Du sicher bist, dass sie nicht mehr gebraucht werden oder Du das Abfragen der übertragenen Daten mit dem Schlüsselwort `range` beenden willst.

## Select

In den vorherigen Beispielen haben wir bisher immer nur einen Datenkanal verwendet, aber wie können wir Gebrauch von mehreren Channels machen? Go erlaubt es, mit dem Schlüsselwort `select` viele Kanäle nach Daten zu belauschen.

`select` stoppt standardmäßig eine Goroutine und wird einzig ausgeführt, wenn einer der Channels Daten sendet oder empfängt. Sollten mehrere Kanäle zur gleichen Zeit aktiv sein, wird ein zufälliger ausgewählt.

    package main

    import "fmt"

    func fibonacci(c, quit chan int) {
        x, y := 1, 1
        for {
            select {
            case c <- x:
                x, y = y, x + y
            case <-quit:
            fmt.Println("Fertig")
                return
            }
        }
    }

    func main() {
        c := make(chan int)
        quit := make(chan int)
        go func() {
            for i := 0; i < 10; i++ {
                fmt.Println(<-c)
            }
            quit <- 0
        }()
        fibonacci(c, quit)
    }
    

`select` hat ebenfalls einen Standardfall wie `switch`, mit dem Namen `default`. Wenn kein Datenkanal aktiv sein sollte, wird der Standardfall ausgeführt (es wird auf keinen Kanal mehr gewartet).

    select {
    case i := <-c:
        // Benutze i
    default:
        // Dieser Code wird ausgeführt, sollte c gestoppt worden sein
    }
    
## Zeitüberschreitung

Manchmal kann es vorkommen, dass eine Goroutine gestoppt wird. Wie können wir verhindern, dass daraus resultierend das gesamte Programm aufhört zu arbeiten? Es ist ganz einfach. Es muss lediglich eine Zeitüberschreitung in `select` festgelegt werden. 

    func main() {
        c := make(chan int)
        o := make(chan bool)
        go func() {
            for {
                select {
                    case v := <- c:
                        println(v)
                    case <- time.After(5 * time.Second):
                        println("Zeitüberschreitung")
                        o <- true
                        break
                }
            }
        }()
        <- o
    }
    
## Runtime goroutine

Das Paket `runtime` beinhaltet ein paar Funktionen zum Umgang mit Goroutinen.

- `runtime.Goexit()`

    Verlässt die aktuelle Goroutine, aber verzögerte Funktionen werden wie gewohnt ausgeführt.
    
- `runtime.Gosched()`

    Lässt die CPU vorerst andere Goroutinen ausführen und kehrt nach einiger Zeit zum Ausgangspunkt zurück.
    
- `runtime.NumCPU() int`

    Gibt die Anzahl der Rechenkerne zurück.

- `runtime.NumGoroutine() int`

    Gibt die Anzahl der Goroutinen zurück.

- `runtime.GOMAXPROCS(n int) int`

    Legt die Anzahl der Rechenkerne fest, die benutzt werden sollen.

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Interfaces](02.6.md)
- Nächster Abschnitt: [Zusammenfassung](02.8.md)

================================================
FILE: de/02.8.md
================================================
# 2.8 Zusammenfassung

In diesem Kapitel haben wir uns hauptsächlich mit den 25 Schlüsselwörtern in Go auseinandergesetzt. Schauen wir sie und ihre Funktionweise uns noch einmal an.

    break    default      func    interface    select
    case     defer        go      map          struct
    chan     else         goto    package      switch
    const    fallthrough  if      range        type
    continue for          import  return       var
    
- `var` und `const` werden benutzt, um Variablen und Konstanten zu definieren.
- `package` und `import` sind für die Nutzung von Paketen nötig.
- `func` wird zur Definition von Funktionen und Methoden verwendet.
- `return` wird genutzt, um Werte von Funktionen und Methoden zurückzugeben.
- `defer` wird genutzt, um Funktionen zu definieren, die als letzte Anweisung ausgeführt werden.
- `go` definiert und startet eine neue Goroutine.
- `select` erlaubt das Kommunizieren über mehrere Channels.
- `interface` definiert ein Interface.
- `struct` lässt uns speziell angepasste Datentypen erstellen.
- `break`, `case`, `continue`, `for`, `fallthrough`, `else`, `if`, `switch`, `goto` und `default` wurden in Abschnitt 2.3 vorgestellt.
- `chan` ist ein Datentypen für Channel, die es erlauben, zwischen Goroutinen zu kommunizieren.
- `type` dient zur Erstellung eigener Datentypen.
- `map` definiert eine Map, welche Hashtabellen in anderen Programmiersprachen ähneln.
- `range` wird genutzt, um Daten aus einem `slice`, einer `map` oder einem`channel` zu erhalten.

Wenn Du verstanden hast, wie die 25 Schlüsselwörter einzusetzen sind, dann hast Du bereits eine Menge über Go gelernt.

## Links

- [Inhaltsverzeichnis](preface.md)
- Vorheriger Abschnitt: [Nebenläufigkeit](02.7.md)
- Nächstes Kapitel: [Grundlagen des Internets](03.0.md)


================================================
FILE: de/03.0.md
================================================
# 3 Internet Grundlagen

Der Grund warum du dieses Buch liest, ist das du lernen möchtest wie man mit Go Webanwendungen erstellt. Wie ich schon sagte, stellt Go viele mächtige Pakete wie `http` zur Verfügung. Die Pakete können dir eine große Hilfe sein um Webanwendungen zu erstellen. In den nächsten Kapiteln werde ich dir hierzu alles beibringen, was du wissen musst.    Wir werden in diesem Kapitel über einige Konzepte des Internet und wie man Webanwendung mit Go ausführt sprechen.

## Links

- [Directory](preface.md)
- Previous chapter: [Chapter 2 Summary](02.8.md)
- Next section: [Web working principles](03.1.md)


================================================
FILE: de/03.1.md
================================================
# Web working principles

Every time you open your browsers, type some URLs and press enter, you will see beautiful web pages appear on your screen. But do you know what is happening behind these simple actions?

Normally, your browser is a client. After you type a URL, it takes the host part of the URL and sends it to a DNS server in order to get the IP address of the host. Then it connects to the IP address and asks to setup a TCP connection. The browser sends HTTP requests through the connection. The server handles them and replies with HTTP responses containing the content that make up the web page. Finally, the browser renders the body of the web page and disconnects from the server.

![](images/3.1.web2.png?raw=true)

Figure 3.1 Processes of users visit a website

A web server, also known as an HTTP server, uses the HTTP protocol to communicate with clients. All web browsers can be considered clients.

We can divide the web's working principles into the following steps:

- Client uses TCP/IP protocol to connect to server.
- Client sends HTTP request packages to server.
- Server returns HTTP response packages to client. If the requested resources include dynamic scripts, server calls script engine first.
- Client disconnects from server, starts rendering HTML.

This is a simple work flow of HTTP affairs -notice that the server closes its connections after it sends data to the clients, then waits for the next request.

## URL and DNS resolution

We always use URLs to access web pages, but do you know how URLs work?

The full name of a URL is Uniform Resource Locator. It's for describing resources on the internet and its basic form is as follows.

	scheme://host[:port#]/path/.../[?query-string][#anchor]
	scheme         assign underlying protocol (such as HTTP, HTTPS, FTP)
	host           IP or domain name of HTTP server
	port#          default port is 80, and it can be omitted in this case. If you want to use other ports, you must specify which port. For example, http://www.cnblogs.com:8080/
	path           resources path
	query-string   data are sent to server
	anchor         anchor
	
DNS is an abbreviation of Domain Name System. It's the naming system for computer network services, and it converts domain names to actual IP addresses, just like a translator.

![](images/3.1.dns_hierachy.png?raw=true)

Figure 3.2 DNS working principles

To understand more about its working principle, let's see the detailed DNS resolution process as follows.

1. After typing the domain name `www.qq.com` in the browser, the operating system will check if there are any mapping relationships in the hosts' files for this domain name. If so, then the domain name resolution is complete.
2. If no mapping relationships exist in the hosts' files, the operating system will check if any cache exists in the DNS. If so, then the domain name resolution is complete.
3. If no mapping relationships exist in both the host and DNS cache, the operating system finds the first DNS resolution server in your TCP/IP settings, which is likely your local DNS server. When the local DNS server receives the query, if the domain name that you want to query is contained within the local configuration of its regional resources, it returns the results to the client. This DNS resolution is authoritative.
4. If the local DNS server doesn't contain the domain name but a mapping relationship exists in the cache, the local DNS server gives back this result to the client. This DNS resolution is not authoritative.
5. If the local DNS server cannot resolve this domain name either by configuration of regional resources or cache, it will proceed to the next step, which depends on the local DNS server's settings. 
-If the local DNS server doesn't enable forwarding, it routes the request to the root DNS server, then returns the IP address of a top level DNS server which may know the domain name, `.com` in this case. If the first top level DNS server doesn't recognize the domain name, it again reroutes the request to the next top level DNS server until it reaches one that recognizes the domain name. Then the top level DNS server asks this next level DNS server for the IP address corresponding to `www.qq.com`.
-If the local DNS server has forwarding enabled, it sends the request to an upper level DNS server. If the upper level DNS server also doesn't recognize the domain name, then the request keeps getting rerouted to higher levels until it finally reaches a DNS server which recognizes the domain name.

Whether or not the local DNS server enables forwarding, the IP address of the domain name always returns to the local DNS server, and the local DNS server sends it back to the client.

![](images/3.1.dns_inquery.png?raw=true)

Figure 3.3 DNS resolution work flow

`Recursive query process` simply means that the enquirers change in the process. Enquirers do not change in `Iterative query` processes.

Now we know clients get IP addresses in the end, so the browsers are communicating with servers through IP addresses.

## HTTP protocol

The HTTP protocol is a core part of web services. It's important to know what the HTTP protocol is before you understand how the web works.

HTTP is the protocol that is used to facilitate communication between browsers and web servers. It is based on the TCP protocol and usually uses port 80 on the side of the web server. It is a protocol that utilizes the request-response model -clients send requests and servers respond. According to the HTTP protocol, clients always setup new connections and send HTTP requests to servers. Servers are not able to connect to clients proactively, or establish callback connections. The connection between a client and a server can be closed by either side. For example, you can cancel your download request and HTTP connection and your browser will disconnect from the server before you finish downloading.

The HTTP protocol is stateless, which means the server has no idea about the relationship between the two connections even though they are both from same client. To solve this problem, web applications use cookies to maintain the state of connections.

Because the HTTP protocol is based on the TCP protocol, all TCP attacks will affect HTTP communications in your server. Examples of such attacks are SYN flooding, DoS and DDoS attacks.

### HTTP request package (browser information)

Request packages all have three parts: request line, request header, and body. There is one blank line between header and body. 

	GET /domains/example/ HTTP/1.1      // request line: request method, URL, protocol and its version
	Host:www.iana.org             // domain name
	User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4            // browser information
	Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    // mime that clients can accept
	Accept-Encoding:gzip,deflate,sdch     // stream compression
	Accept-Charset:UTF-8,*;q=0.5      // character set in client side
	// blank line
	// body, request resource arguments (for example, arguments in POST)

We use fiddler to get the following request information.

![](images/3.1.http.png?raw=true)

Figure 3.4 Information of a GET request caught by fiddler

![](images/3.1.httpPOST.png?raw=true)

Figure 3.5 Information of a POST request caught by fiddler

**We can see that GET does not have a request body, unlike POST, which does.**

There are many methods you can use to communicate with servers in HTTP; GET, POST, PUT and DELETE are the 4 basic methods that we typically use. A URL represents a resource on a network, so these 4 methods define the query, change, add and delete operations that can act on these resources. GET and POST are very commonly used in HTTP. GET can append query parameters to the URL, using `?` to separate the URL and parameters and `&` between the arguments, like `EditPosts.aspx?name=test1&id=123456`. POST puts data in the request body because the URL implements a length limitation via the browser. Thus, POST can submit much more data than GET. Also, when we submit user names and passwords, we don't want this kind of information to appear in the URL, so we use POST to keep them invisible.

### HTTP response package (server information)

Let's see what information is contained in the response packages.

	HTTP/1.1 200 OK                     // status line
	Server: nginx/1.0.8                 // web server software and its version in the server machine
	Date:Date: Tue, 30 Oct 2012 04:14:25 GMT        // responded time
	Content-Type: text/html             // responded data type
	Transfer-Encoding: chunked          // it means data were sent in fragments
	Connection: keep-alive              // keep connection 
	Content-Length: 90                  // length of body
	// blank line
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... // message body

The first line is called the status line. It supplies the HTTP version, status code and status message.

The status code informs the client of the status of the HTTP server's response. In HTTP/1.1, 5 kinds of status codes were defined:

	- 1xx Informational
	- 2xx Success
	- 3xx Redirection
	- 4xx Client Error
	- 5xx Server Error

Let's see more examples about response packages. 200 means server responded correctly, 302 means redirection. 

![](images/3.1.response.png?raw=true)

Figure 3.6 Full information for visiting a website

### HTTP is stateless and Connection: keep-alive

The term stateless doesn't mean that the server has no ability to keep a connection. It simply means that the server doesn't recognize any relationships between any two requests.

In HTTP/1.1, Keep-alive is used by default. If clients have additional requests, they will use the same connection for them.

Notice that Keep-alive cannot maintian one connection forever; the application running in the server determines the limit with which to keep the connection alive for, and in most cases you can configure this limit. 

## Request instance

![](images/3.1.web.png?raw=true)

Figure 3.7 All packages for opening one web page

We can see the entire communication process between client and server from the above picture. You may notice that there are many resource files in the list; these are called static files, and Go has specialized processing methods for these files.

This is the most important function of browsers: to request for a URL and retrieve data from web servers, then render the HTML. If it finds some files in the DOM such as CSS or JS files, browsers will request these resources from the server again until all the resources finish rendering on your screen.

Reducing HTTP request times is one way of improving the loading speed of web pages. By reducing the number of CSS and JS files that need to be loaded, both request latencies and pressure on your web servers can be reduced at the same time.

## Links

- [Directory](preface.md)
- Previous section: [Web foundation](03.0.md)
- Next section: [Build a simple web server](03.2.md)


================================================
FILE: de/03.2.md
================================================
# 3.2 Build a simple web server

We've discussed that web applications are based on the HTTP protocol, and Go provides full HTTP support in the `net/http` package. It's very easy to set a web server up using this package.

## Use http package setup a web server

	package main

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

	func sayhelloName(w http.ResponseWriter, r *http.Request) {
    	r.ParseForm()  // parse arguments, you have to call this by yourself
    	fmt.Println(r.Form)  // print form information in server side
    	fmt.Println("path", r.URL.Path)
    	fmt.Println("scheme", r.URL.Scheme)
    	fmt.Println(r.Form["url_long"])
    	for k, v := range r.Form {
        	fmt.Println("key:", k)
        	fmt.Println("val:", strings.Join(v, ""))
    	}
    	fmt.Fprintf(w, "Hello astaxie!") // send data to client side
	}

	func main() {
    	http.HandleFunc("/", sayhelloName) // set router
    	err := http.ListenAndServe(":9090", nil) // set listen port
    	if err != nil {
        	log.Fatal("ListenAndServe: ", err)
    	}
	}
	
After we execute the above code, the server begins listening to port 9090 in local host.

Open your browser and visit `http://localhost:9090`. You can see that `Hello astaxie` is on your screen.

Let's try another address with additional arguments: `http://localhost:9090/?url_long=111&url_long=222`

Now let's see what happens on both the client and server sides.

You should see the following information on the server side:

![](images/3.2.goweb.png?raw=true)

Figure 3.8 Server printed information

As you can see, we only need to call two functions in order to build a simple web server.

If you are working with PHP, you're probably asking whether or not we need something like Nginx or Apache. The answer is we no, since Go listens to the TCP port by itself, and the function `sayhelloName` is the logic function just like a controller in PHP.

If you are working with Python you should know tornado, and the above example is very similar to that.

If you are working with Ruby, you may notice it is like script/server in ROR.

We used two simple functions to setup a simple web server in this section, and this simple server already has the capacity for high concurrency operations. We will talk about how to utilize this in the next two sections.

## Links

- [Directory](preface.md)
- Previous section: [Web working principles](03.1.md)
- Next section: [How Go works with web](03.3.md)


================================================
FILE: de/03.3.md
================================================
# 3.3 How Go works with web

We learned to use the `net/http` package to build a simple web server in the previous section, and all those working principles are the same as those we will talk about in the first section of this chapter.

## Concepts in web principles

Request: request data from users, including POST, GET, Cookie and URL.

Response: response data from server to clients.

Conn: connections between clients and servers.

Handler: Request handling logic and response generation.

## http package operating mechanism

The following picture shows the work flow of a Go web server.

![](images/3.3.http.png?raw=true)

Figure 3.9 http work flow

1. Create a listening socket, listen to a port and wait for clients.
2. Accept requests from clients.
3. Handle requests, read HTTP header. If the request uses POST method, read data in the message body and pass them to handlers. Finally, socket returns response data to clients.

Once we know the answers to the three following questions, it's easy to know how the web works in Go.

- How do we listen to a port?
- How do we accept client requests?
- How do we allocate handlers?

In the previous section we saw that Go uses `ListenAndServe` to handle these steps: initialize a server object, call `net.Listen("tcp", addr)` to setup a TCP listener and listen to a specific address and port.

Let's take a look at the `http` package's source code.

	//Build version go1.1.2.
	func (srv *Server) Serve(l net.Listener) error {
		defer l.Close()
		var tempDelay time.Duration // how long to sleep on accept failure
		for {
			rw, e := l.Accept()
			if e != nil {
				if ne, ok := e.(net.Error); ok && ne.Temporary() {
					if tempDelay == 0 {
						tempDelay = 5 * time.Millisecond
					} else {
						tempDelay *= 2
					}
					if max := 1 * time.Second; tempDelay > max {
						tempDelay = max
					}
					log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay)
					time.Sleep(tempDelay)
					continue
				}
				return e
			}
			tempDelay = 0
			c, err := srv.newConn(rw)
			if err != nil {
				continue
			}
			go c.serve()
		}
	}

	
How do we accept client requests after we begin listening to a port? In the source code, we can see that `srv.Serve(net.Listener)` is called to handle client requests. In the body of the function there is a `for{}`. It accepts a request, creates a new connection then starts a new goroutine, passing the request data to the `go c.serve()` goroutine. This is how Go supports high concurrency, and every goroutine is independent.

How do we use specific functions to handle requests? `conn` parses request `c.ReadRequest()` at first, then gets the corresponding handler: `handler := c.server.Handler` which is the second argument we passed when we called `ListenAndServe`. Because we passed `nil`, Go uses its default handler `handler = DefaultServeMux`. So what is `DefaultServeMux` doing here? Well, its the router variable which can call handler functions for specific URLs. Did we set this? Yes, we did. We did this in the first line where we used `http.HandleFunc("/", sayhelloName)`. We're using this function to register the router rule for the "/" path. When the URL is `/`, the router calls the function `sayhelloName`. DefaultServeMux calls ServerHTTP to get handler functions for different paths, calling `sayhelloName` in this specific case. Finally, the server writes data and responds to clients.

Detailed work flow:

![](images/3.3.illustrator.png?raw=true)

Figure 3.10 Work flow of handling an HTTP request

I think you should know how Go runs web servers now.

## Links

- [Directory](preface.md)
- Previous section: [Build a simple web server](03.2.md)
- Next section: [Get into http package](03.4.md)


================================================
FILE: de/03.4.md
================================================
# 3.4 Get into http package

In previous sections, we learned about the work flow of the web and talked a little bit about Go's `http` package. In this section, we are going to learn about two core functions in the `http` package: Conn and ServeMux.

## goroutine in Conn

Unlike normal HTTP servers, Go uses goroutines for every job initiated by Conn in order to achieve high concurrency and performance, so every job is independent.

Go uses the following code to wait for new connections from clients.

	c, err := srv.newConn(rw)
	if err != nil {
    	continue
	}
	go c.serve()
	
As you can see, it creates a new goroutine for every connection, and passes the handler that is able to read data from the request to the goroutine.

## Customized ServeMux

We used Go's default router in previous sections when discussing conn.server, with the router passing request data to a back-end handler.

The struct of the default router:

	type ServeMux struct {
    	mu sync.RWMutex   // because of concurrency, we have to use a mutex here
    	m  map[string]muxEntry  // router rules, every string mapping to a handler
	}
	
The struct of muxEntry:

	type muxEntry struct {
    	explicit bool   // exact match or not
    	h        Handler
	}
	
The interface of Handler:

	type Handler interface {
    	ServeHTTP(ResponseWriter, *Request)  // routing implementer
	}
	
`Handler` is an interface, but if the function `sayhelloName` didn't implement this interface, then how did we add it as handler? The answer lies in another type called `HandlerFunc` in the `http` package. We called `HandlerFunc` to define our `sayhelloName` method, so `sayhelloName` implemented `Handler` at the same time. It's like we're calling `HandlerFunc(f)`, and the function `f` is force converted to type `HandlerFunc`.

	type HandlerFunc func(ResponseWriter, *Request)

	// ServeHTTP calls f(w, r).
	func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    	f(w, r)
	}
	
How does the router call handlers after we set the router rules?

The router calls `mux.handler.ServeHTTP(w, r)` when it receives requests. In other words, it calls the `ServeHTTP` interface of the handlers which have implemented it.

Now, let's see how `mux.handler` works.

	func (mux *ServeMux) handler(r *Request) Handler {
    	mux.mu.RLock()
    	defer mux.mu.RUnlock()

    	// Host-specific pattern takes precedence over generic ones
    	h := mux.match(r.Host + r.URL.Path)
    	if h == nil {
        	h = mux.match(r.URL.Path)
    	}
    	if h == nil {
        	h = NotFoundHandler()
    	}
    	return h
	}
	
The router uses the request's URL as a key to find the corresponding handler saved in the map, then calls handler.ServeHTTP to execute functions to handle the data.

You should understand the default router's work flow by now, and Go actually supports customized routers. The second argument of `ListenAndServe` is for configuring customized routers. It's an interface of `Handler`. Therefore, any router that implements the `Handler` interface can be used.

The following example shows how to implement a simple router.

	package main

	import (
    	"fmt"
    	"net/http"
	)

	type MyMux struct {
	}

	func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    	if r.URL.Path == "/" {
        	sayhelloName(w, r)
        	return
    	}
    	http.NotFound(w, r)
    	return
	}

	func sayhelloName(w http.ResponseWriter, r 	*http.Request) {
    	fmt.Fprintf(w, "Hello myroute!")
	}

	func main() {
    	mux := &MyMux{}
    	http.ListenAndServe(":9090", mux)
	}
	
## Go code execution flow

Let's take a look at the whole execution flow.

- Call `http.HandleFunc`
	1. Call HandleFunc of DefaultServeMux
	2. Call Handle of DefaultServeMux
	3. Add router rules to map[string]muxEntry of DefaultServeMux
- Call `http.ListenAndServe(":9090", nil)`
	1. Instantiate Server
	2. Call ListenAndServe method of Server
	3. Call net.Listen("tcp", addr) to listen to port
	4. Start a loop and accept requests in the loop body
	5. Instantiate a Conn and start a goroutine for every request: `go c.serve()`
	6. Read request data: `w, err := c.readRequest()`
	7. Check whether handler is empty or not, if it's empty then use DefaultServeMux
	8. Call ServeHTTP of handler
	9. Execute code in DefaultServeMux in this case
	10. Choose handler by URL and execute code in that handler function: `mux.handler.ServeHTTP(w, r)`
	11. How to choose handler:
		A. Check router rules for this URL
		B. Call ServeHTTP in that handler if there is one
		C. Call ServeHTTP of NotFoundHandler otherwise
			
## Links

- [Directory](preface.md)
- Previous section: [How Go works with web](03.3.md)
- Next section: [Summary](03.5.md)


================================================
FILE: de/03.5.md
================================================
# 3.5 Summary

In this chapter, we introduced HTTP, DNS resolution flow and how to build a simple web server. Then we talked about how Go implements web servers for us by looking at the source code of the `net/http` package.

I hope that you now know much more about web development, and you should see that it's quite easy and flexible to build a web application in Go.

## Links

- [Directory](preface.md)
- Previous section: [Get into http package](03.4.md)
- Next chapter: [User form](04.0.md)


================================================
FILE: de/04.0.md
================================================
# 4 User form

A user form is something that is very commonly used when developping web applications. It provides the ability to communicate between clients and servers. You must be very familiar with forms if you are a web developer; if you are a C/C++ programmer, you may want to ask: what is a user form?

A form is an area that contains form elements. Users can input information into form elements like text boxes, drop down lists, radio buttons, check boxes, etc. We use the form tag `<form>` to define forms.

	<form>
	...
	input elements
	...
	</form>

Go already has many convenient functions to deal with user forms. You can easily get form data in HTTP requests, and they are easy to integrate into your own web applications. In section 4.1, we are going to talk about how to handle form data in Go. Also, since you cannot trust any data coming from the client side, you must first verify the data before using it. We'll go through some examples about how to verify form data in section 4.2.

We say that HTTP is stateless. How can we identify that certain forms are from the same user? And how do we make sure that one form can only be submitted once? We'll look at some details concerning cookies (a cookie is information that can be saved on the client side and added to the request header when the request is sent to the server) in both sections 4.3 and 4.4.

Another big use-case of forms is uploading files. In section 4.5, you will learn how to do this as well as controlling the file upload size before it begins uploading, in Go.

## Links

- [Directory](preface.md)
- Previous chapter: [Chapter 3 Summary](03.5.md)
- Next section: [Process form inputs](04.1.md)


================================================
FILE: de/04.1.md
================================================
# 4.1 Process form inputs

Before we begin, let's take a look at a simple example of a typical user form, saved as `login.gtpl` in your project folder.

	<html>
	<head>
	<title></title>
	</head>
	<body>
	<form action="/login" method="post">
    	Username:<input type="text" name="username">
    	Password:<input type="password" name="password">
    	<input type="submit" value="Login">
	</form>
	</body>
	</html>

This form will submit to `/login` on the server. After the user clicks the login button, the data will be sent to the `login` handler registered by the server router. Then we need to know whether it uses the POST method or GET.

This is easy to find out using the `http` package. Let's see how to handle the form data on the login page.

	package main

	import (
		"fmt"
		"html/template"
		"log"
		"net/http"
		"strings"
	)

	func sayhelloName(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()  //Parse url parameters passed, then parse the response packet for the POST body (request body)
		// attention: If you do not call ParseForm method, the following data can not be obtained form
		fmt.Println(r.Form) // print information on server side.
		fmt.Println("path", r.URL.Path)
		fmt.Println("scheme", r.URL.Scheme)
		fmt.Println(r.Form["url_long"])
		for k, v := range r.Form {
			fmt.Println("key:", k)
			fmt.Println("val:", strings.Join(v, ""))
		}
		fmt.Fprintf(w, "Hello astaxie!") // write data to response
	}

	func login(w http.ResponseWriter, r *http.Request) {
		fmt.Println("method:", r.Method) //get request method
		if r.Method == "GET" {
			t, _ := template.ParseFiles("login.gtpl")
			t.Execute(w, nil)
		} else {
			r.ParseForm()
			// logic part of log in
			fmt.Println("username:", r.Form["username"])
			fmt.Println("password:", r.Form["password"])
		}
	}

	func main() {
		http.HandleFunc("/", sayhelloName) // setting router rule
		http.HandleFunc("/login", login)
		err := http.ListenAndServe(":9090", nil) // setting listening port
		if err != nil {
			log.Fatal("ListenAndServe: ", err)
		}
	}


Here we use `r.Method` to get the request method, and it returns an http verb -"GET", "POST", "PUT", etc.

In the `login` function, we use `r.Method` to check whether it's a login page or login processing logic. In other words, we check to see whether the user is simply opening the page, or trying to log in. Serve shows the page only when the request comes in via the GET method, and it executes the login logic when the request uses the POST method.

You should see the following interface after opening `http://127.0.0.1:9090/login` in your browser.

![](images/4.1.login.png?raw=true)

Figure 4.1 User login interface

The server will not print anything until after we type in a username and password, because the handler doesn't parse the form until we call `r.ParseForm()`. Let's add `r.ParseForm()` before `fmt.Println("username:", r.Form["username"])`, compile our program and test it again. You will find that the information is printed on the server side now.

`r.Form` contains all of the request arguments, for instance the query-string in the URL and the data in POST and PUT. If the data has conflicts, for example parameters that have the same name, the server will save the data into a slice with multiple values. The Go documentation states that Go will save the data from GET and POST requests in different places.

Try changing the value of the action in the form `http://127.0.0.1:9090/login` to `http://127.0.0.1:9090/login?username=astaxie` in the `login.gtpl` file, test it again, and you will see that the slice is printed on the server side.

![](images/4.1.slice.png?raw=true)

Figure 4.2 Server prints request data

The type of `request.Form` is `url.Values`. It saves data with the format `key=value`.

	v := url.Values{}
	v.Set("name", "Ava")
	v.Add("friend", "Jess")
	v.Add("friend", "Sarah")
	v.Add("friend", "Zoe")
	// v.Encode() == "name=Ava&friend=Jess&friend=Sarah&friend=Zoe"
	fmt.Println(v.Get("name"))
	fmt.Println(v.Get("friend"))
	fmt.Println(v["friend"])

**Tips** Requests have the ability to access form data using the `FormValue()` method. For example, you can change `r.Form["username"]` to `r.FormValue("username")`, and Go calls `r.ParseForm` automatically. Notice that it returns the first value if there are arguments with the same name, and it returns an empty string if there is no such argument.

## Links

- [Directory](preface.md)
- Previous section: [User form](04.0.md)
- Next section: [Verification of inputs](04.2.md)


================================================
FILE: de/04.2.md
================================================
# 4.2 Verification of inputs

One of the most important principles in web development is that you cannot trust anything from client side user forms. You have to verify all incoming data before use it. Many websites are affected by this problem, which is simple yet crucial.

There are two ways of verify form data that are commonly used. One is JavaScript verification in the front-end, and the other is server verification in the back-end. In this section, we are going to talk about server side verification in web development.

## Required fields

Sometimes we require that users input some fields but they don't, for example in the previous section when we required a username. You can use the `len` function to get the length of a field in order to ensure that users have entered this information.

	if len(r.Form["username"][0])==0{
    	// code for empty field
	}

`r.Form` treats different form element types differently when they are blank. For empty textboxes, text areas and file uploads, it returns an empty string; for radio buttons and check boxes, it doesn't even create the corresponding items. Instead, you will get errors if you try to access it. Therefore, it's safer to use `r.Form.Get()` to get field values since it will always return empty if the value does not exist. On the other hand, `r.Form.Get()` can only get one field value at a time, so you need to use `r.Form` to get the map of values.

## Numbers

Sometimes you only need numbers for the field value. For example, let's say that you require the age of a user in integer form only, i.e 50 or 10, instead of "old enough" or "young man". If we require a positive number, we can convert the value to the `int` type first, then process it.

	getint,err:=strconv.Atoi(r.Form.Get("age"))
	if err!=nil{
    	// error occurs when convert to number, it may not a number
	}

	// check range of number
	if getint >100 {
    	// too big
	}

Another way to do this is using regular expressions.

	if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m {
    	return false
	}
	
For high performance purposes, regular expressions are not efficient, however simple regular expressions are usually fast enough. If you are familiar with regular expressions, it's a very convenient way to verify data. Notice that Go uses [RE2](http://code.google.com/p/re2/wiki/Syntax), so all UTF-8 characters are supported.

## Chinese

Sometimes we need users to input their Chinese names and we have to verify that they all use Chinese rather than random characters. For Chinese verification, regular expressions are the only way.

	if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m {
    	return false
	}

## English letters

Sometimes we need users to input only English letters. For example, we require someone's English name, like astaxie instead of asta谢. We can easily use regular expressions to perform our verification.

	if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m {
    	return false
	}

## E-mail address

If you want to know whether users have entered valid E-mail addresses, you can use the following regular expression:

	if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, r.Form.Get("email")); !m {
    	fmt.Println("no")
	}else{
    	fmt.Println("yes")
	}

## Drop down list

Let's say we require an item from our drop down list, but instead we get a value fabricated by hackers. How do we prevent this from happening? 

Suppose we have the following `<select>`:

	<select name="fruit">
	<option value="apple">apple</option>
	<option value="pear">pear</option>
	<option value="banana">banana</option>
	</select>

We can use the following strategy to sanitize our input:

	slice:=[]string{"apple","pear","banana"}

	for _, v := range slice {
    	if v == r.Form.Get("fruit") {
        	return true
    	}
	}
	return false

All the functions I've shown above are in my open source project for operating on slices and maps: [https://github.com/astaxie/beeku](https://github.com/astaxie/beeku)

## Radio buttons

If we want to know whether the user is male or female, we may use a radio button, returning 1 for male and 2 for female. However, some little kid who just read his first book on HTTP, decides to send to you a 3. Will your program have have exception? As you can see, we need to use the same method as we did for our drop down list to make sure that only expected values are returned by our radio button.

	<input type="radio" name="gender" value="1">Male
	<input type="radio" name="gender" value="2">Female

And we use following code to verify the input:

	slice:=[]int{1,2}

	for _, v := range slice {
    	if v == r.Form.Get("gender") {
        	return true
    	}
	}
	return false

## Check boxes

Suppose there are some check boxes for user interests, and that you don't want extraneous values here either.

	<input type="checkbox" name="interest" value="football">Football
	<input type="checkbox" name="interest" value="basketball">Basketball
	<input type="checkbox" name="interest" value="tennis">Tennis

In this case, the sanitization is a little bit different than verifying the button and check box inputs since here we get a slice from the check boxes.

	slice:=[]string{"football","basketball","tennis"}
	a:=Slice_diff(r.Form["interest"],slice)
	if a == nil{
    	return true
	}

	return false 

## Date and time

Suppose you want users to input valid dates or times. Go has the `time` package for converting year, month and day to their corresponding times. After that, it's easy to check it.

	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Printf("Go launched at %s\n", t.Local())

After you have the time, you can use the `time` package for more operations, depending on your needs.

In this section, we've discussed some common methods for verifying form data server side. I hope that you now understand more about data verification in Go, especially how to use regular expressions to your advantage.

## Links

- [Directory](preface.md)
- Previous section: [Process form inputs](04.1.md)
- Next section: [Cross site scripting](04.3.md)


================================================
FILE: de/04.3.md
================================================
# 4.3 Cross site scripting

Today's websites have much more dynamic content in order to improve user experience, which means that we must provide dynamic information depending on every individual's behavior. Unfortunately, there is a thing called "Cross site scripting" (known as "XSS") always attacking dynamic websites, from which static websites are completely fine at this time.

Attackers often inject malicious scripts like JavaScript, VBScript, ActiveX or Flash into those websites that have loopholes. Once they have successfully injected their scripts, user information can be stolen and your website can be flooded with spam. The attackers can also change user settings to whatever they want.

If you want to prevent this kind of attack, you should combine the two following approaches: 

- Verification of all data from users, which we talked about in the previous section.
- Carefully handle data that will be sent to clients in order to prevent any injected scripts from running on browsers.

So how can we do these two things in Go? Fortunately, the `html/template` package has some useful functions to escape data as follows:

- `func HTMLEscape(w io.Writer, b []byte)` escapes b to w.
- `func HTMLEscapeString(s string) string` returns a string after escaping from s.
- `func HTMLEscaper(args ...interface{}) string` returns a string after escaping from multiple arguments.

Let's change the example in section 4.1:

	fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print at server side
	fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
	template.HTMLEscape(w, []byte(r.Form.Get("username"))) // responded to clients

If someone tries to input the username as `<script>alert()</script>`, we will see the following content in the browser:

![](images/4.3.escape.png?raw=true)

Figure 4.3 JavaScript after escaped

Functions in the `html/template` package help you to escape all HTML tags. What if you just want to print `<script>alert()</script>` to browsers? You should use `text/template` instead.

	import "text/template"
	...
	t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
	err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")

Output:

	Hello, <script>alert('you have been pwned')</script>!

Or you can use the `template.HTML` type : 
Variable content will not be escaped if its type is `template.HTML`.

	import "html/template"
	...
	t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
	err = t.ExecuteTemplate(out, "T", template.HTML("<script>alert('you have been pwned')</script>"))

Output:

	Hello, <script>alert('you have been pwned')</script>!

One more example of escaping:

	import "html/template"
	...
	t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
	err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")

Output:

	Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;!

## Links

- [Directory](preface.md)
- Previous section: [Verification of inputs](04.2.md)
- Next section: [Duplicate submissions](04.4.md)


================================================
FILE: de/04.4.md
================================================
# 4.4 Duplicate submissions

I don't know if you've ever seen some blogs or BBS' that have more than one posts that are exactly the same, but I can tell you that it's because users submitted duplicate post forms. There many things that can cause duplicate submissions; sometimes users just double click the submit button, or they want to modify some content after posting and press the back button. Other times it's the intentional actions of malicious users. It's easy to see how duplicate submissions can lead to many problems. Thus, we have to use effective means to prevent it.

The solution is to add a hidden field with a unique token to your form, and to always check this token before processing the incoming data. Also, if you are using Ajax to submit a form, use JavaScript to disable the submit button once the form has been submitted.

Let's improve the example from section 4.2:

	<input type="checkbox" name="interest" value="football">Football
	<input type="checkbox" name="interest" value="basketball">Basketball
	<input type="checkbox" name="interest" value="tennis">Tennis
	Username:<input type="text" name="username">
	Password:<input type="password" name="password">
	<input type="hidden" name="token" value="{{.}}">
	<input type="submit" value="Login">

We use an MD5 hash (time stamp) to generate the token, and added it to both a hidden field on the client side form and a session cookie on the server side (Chapter 6). We can then use this token to check whether or not this form was submitted.

	func login(w http.ResponseWriter, r *http.Request) {
    	fmt.Println("method:", r.Method) // get request method
    	if r.Method == "GET" {
        	crutime := time.Now().Unix()
        	h := md5.New()
        	io.WriteString(h, strconv.FormatInt(crutime, 10))
        	token := fmt.Sprintf("%x", h.Sum(nil))

        	t, _ := template.ParseFiles("login.gtpl")
        	t.Execute(w, token)
    	} else {
        	// log in request
        	r.ParseForm()
        	token := r.Form.Get("token")
        	if token != "" {
        	    // check token validity
        	} else {
        	    // give error if no token
        	}
        	fmt.Println("username length:", len(r.Form["username"][0]))
        	fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print in server side
        	fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
        	template.HTMLEscape(w, []byte(r.Form.Get("username"))) // respond to client
    	}
	}

![](images/4.4.token.png?raw=true)

Figure 4.4 The content in browser after adding a token

You can refresh this page and you will see a different token every time. This ensures that every form is unique.

For now, you can prevent many duplicate submission attacks by adding tokens to your forms, but it cannot prevent all deceptive attacks of this type. There is much more work that needs to be done.
 
## Links

- [Directory](preface.md)
- Previous section: [Cross site scripting](04.3.md)
- Next section: [File upload](04.5.md)


================================================
FILE: de/04.5.md
================================================
# 4.5 File upload

Suppose you have a website like Instagram and you want users to upload their beautiful photos. How would you implement that functionality?

You have to add property `enctype` to the form that you want to use for uploading photos. There are three possible values for this property:

```
application/x-www-form-urlencoded   Transcode all characters before uploading (default).
multipart/form-data   No transcoding. You must use this value when your form has file upload controls.
text/plain    Convert spaces to "+", but no transcoding for special characters.
```


Therefore, the HTML content of a file upload form should look like this:

```
<html>
<head>
   	<title>Upload file</title>
</head>
<body>
<form enctype="multipart/form-data" action="http://127.0.0.1:9090/upload" method="post">
	<input type="file" name="uploadfile" />
	<input type="hidden" name="token" value="{{.}}"/>
	<input type="submit" value="upload" />
</form>
</body>
</html>
```


We need to add a function on the server side to handle this form.

```
http.HandleFunc("/upload", upload)

// upload logic
func upload(w http.ResponseWriter, r *http.Request) {
   	fmt.Println("method:", r.Method)
   	if r.Method == "GET" {
       	crutime := time.Now().Unix()
       	h := md5.New()
       	io.WriteString(h, strconv.FormatInt(crutime, 10))
       	token := fmt.Sprintf("%x", h.Sum(nil))

       	t, _ := template.ParseFiles("upload.gtpl")
       	t.Execute(w, token)
   	} else {
       	r.ParseMultipartForm(32 << 20)
       	file, handler, err := r.FormFile("uploadfile")
       	if err != nil {
           	fmt.Println(err)
           	return
       	}
       	defer file.Close()
       	fmt.Fprintf(w, "%v", handler.Header)
       	f, err := os.OpenFile("./test/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
       	if err != nil {
           	fmt.Println(err)
           	return
       	}
       	defer f.Close()
       	io.Copy(f, file)
   	}
}
```


As you can see, we need to call `r.ParseMultipartForm` for uploading files. The function `maxMemory` argument. After you call `ParseMultipartForm`, the file will be saved in the server memory with `maxMemory` size. If the file size is larger than `maxMemory`, the rest of the data will be saved in a system temporary file. You can use `r.FormFile` to get the file handle and use `io.Copy` to save to your file system.

You don't need to call `r.ParseForm` when you access other non-file fields in the form because Go will call it when it's necessary. Also, calling `ParseMultipartForm` once is enough -multiple calls make no difference.

We use three steps for uploading files as follows:

1. Add `enctype="multipart/form-data"` to your form.
2. Call `r.ParseMultipartForm` on the server side to save the file either to memory or to a temporary file.
3. Call `r.FormFile` to get the file handle and save to the file system.

The file handler is the `multipart.FileHeader`. It uses the following struct:

```
type FileHeader struct {
   	Filename string
   	Header   textproto.MIMEHeader
   	// contains filtered or unexported fields
}
```

![](images/4.5.upload2.png?raw=true)

Figure 4.5 Print information on server after receiving file.

## Clients upload files

I showed an example of using a form to a upload a file. We can impersonate a client form to upload files in Go as well.

```
package main

import (
    "bytes"
    "fmt"
    "io"
    "io/ioutil"
    "mime/multipart"
    "net/http"
    "os"
)

func postFile(filename string, targetUrl string) error {
    bodyBuf := &bytes.Buffer{}
    bodyWriter := multipart.NewWriter(bodyBuf)

    // this step is very important
    fileWriter, err := bodyWriter.CreateFormFile("uploadfile", filename)
    if err != nil {
        fmt.Println("error writing to buffer")
        return err
    }

    // open file handle
    fh, err := os.Open(filename)
    if err != nil {
        fmt.Println("error opening file")
        return err
    }

    //iocopy
    _, err = io.Copy(fileWriter, fh)
    if err != nil {
        return err
    }

    contentType := bodyWriter.FormDataContentType()
    bodyWriter.Close()

    resp, err := http.Post(targetUrl, contentType, bodyBuf)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    resp_body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return err
    }
    fmt.Println(resp.Status)
    fmt.Println(string(resp_body))
    return nil
}

// sample usage
func main() {
    target_url := "http://localhost:9090/upload"
    filename := "./astaxie.pdf"
    postFile(filename, target_url)
}
```


The above example shows you how to use a client to upload files. It uses `multipart.Write` to write files into cache and sends them to the server through the POST method.

If you have other fields that need to write into data, like username, call `multipart.WriteField` as needed.

## Links

- [Directory](preface.md)
- Previous section: [Duplicate submissions](04.4.md)
- Next section: [Summary](04.6.md)


================================================
FILE: de/04.6.md
================================================
# 4.6 Summary

In this chapter, we mainly learned how to process form data in Go through several examples like logging in users and uploading files. We also emphasized that verifying user data is extremely important for website security, and we used one section to talk about how to filter data with regular expressions.

I hope that you now know more about the communication process between client and server. 

## Links

- [Directory](preface.md)
- Previous section: [File upload](04.5.md)
- Next chapter: [Database](05.0.md)


================================================
FILE: de/05.0.md
================================================
# 5 Database

For web developers, the database is at the core of web development. You can save almost anything into a database and query or update data inside it, like user information, products or news articles.

Go doesn't provide any database drivers, but it does have a driver interface defined in the `database/sql` package. People can develop database drivers based on that interface. In section 5.1, we are going to talk about database driver interface design in Go; in sections 5.2 to 5.4, I will introduce some SQL database drivers to you; in section 5.5, i'll present the ORM that i've developed which is based on the `database/sql` interface standard. It's compatible with most drivers that have implemented the `database/sql` interface, and it makes it easy to access databases idiomatically in Go.

NoSQL has been a hot topic in recent years. More websites are deciding to use NoSQL databases as their main database instead of just for the purpose of caching. I will introduce you to two NoSQ
Download .txt
gitextract_hws5bolv/

├── LANGS.md
├── LICENSE.md
├── README.md
├── bn/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── preface.md
│   └── ref.md
├── de/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── preface.md
│   └── ref.md
├── en/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── build.go
│   ├── build.sh
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── eBook/
│   │   ├── 05.0.md
│   │   └── 05.0.md.orig
│   ├── images/
│   │   ├── 1.1.cmd.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.cmd.png~update the structure for gitbook
│   │   ├── 1.1.linux.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.linux.png~update the structure for gitbook
│   │   ├── 1.1.mac.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.mac.png~update the structure for gitbook
│   │   ├── 1.3.go.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.3.go.png~update the structure for gitbook
│   │   ├── 1.4.eclipse1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse1.png~update the structure for gitbook
│   │   ├── 1.4.eclipse2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse2.png~update the structure for gitbook
│   │   ├── 1.4.eclipse3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse3.png~update the structure for gitbook
│   │   ├── 1.4.eclipse4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse4.png~update the structure for gitbook
│   │   ├── 1.4.eclipse5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse5.png~update the structure for gitbook
│   │   ├── 1.4.eclipse6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse6.png~update the structure for gitbook
│   │   ├── 1.4.emacs.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.emacs.png~update the structure for gitbook
│   │   ├── 1.4.idea1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea1.png~update the structure for gitbook
│   │   ├── 1.4.idea2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea2.png~update the structure for gitbook
│   │   ├── 1.4.idea3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea3.png~update the structure for gitbook
│   │   ├── 1.4.idea4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea4.png~update the structure for gitbook
│   │   ├── 1.4.idea5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea5.png~update the structure for gitbook
│   │   ├── 1.4.liteide.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.liteide.png~update the structure for gitbook
│   │   ├── 1.4.sublime1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime1.png~update the structure for gitbook
│   │   ├── 1.4.sublime2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime2.png~update the structure for gitbook
│   │   ├── 1.4.sublime3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime3.png~update the structure for gitbook
│   │   ├── 1.4.sublime4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime4.png~update the structure for gitbook
│   │   ├── 1.4.vim.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.vim.png~update the structure for gitbook
│   │   ├── 13.1.gopath.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath.png~update the structure for gitbook
│   │   ├── 13.1.gopath2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath2.png~update the structure for gitbook
│   │   ├── 13.4.beego.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.4.beego.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap2.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap3.png~update the structure for gitbook
│   │   ├── 14.4.github.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github.png~update the structure for gitbook
│   │   ├── 14.4.github2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github2.png~update the structure for gitbook
│   │   ├── 14.4.github3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github3.png~update the structure for gitbook
│   │   ├── 14.6.pprof.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof.png~update the structure for gitbook
│   │   ├── 14.6.pprof2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof2.png~update the structure for gitbook
│   │   ├── 14.6.pprof3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof3.png~update the structure for gitbook
│   │   ├── 2.2.array.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.array.png~update the structure for gitbook
│   │   ├── 2.2.basic.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.basic.png~update the structure for gitbook
│   │   ├── 2.2.makenew.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.makenew.png~update the structure for gitbook
│   │   ├── 2.2.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice.png~update the structure for gitbook
│   │   ├── 2.2.slice2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice2.png~update the structure for gitbook
│   │   ├── 2.3.init.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.3.init.png~update the structure for gitbook
│   │   ├── 2.4.student_struct.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.4.student_struct.png~update the structure for gitbook
│   │   ├── 2.5.rect_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.rect_func_without_receiver.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_without_receiver.png~update the structure for gitbook
│   │   ├── 3.1.dns2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns2.png~update the structure for gitbook
│   │   ├── 3.1.dns_hierachy.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_hierachy.png~update the structure for gitbook
│   │   ├── 3.1.dns_inquery.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_inquery.png~update the structure for gitbook
│   │   ├── 3.1.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.http.png~update the structure for gitbook
│   │   ├── 3.1.httpPOST.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.httpPOST.png~update the structure for gitbook
│   │   ├── 3.1.response.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.response.png~update the structure for gitbook
│   │   ├── 3.1.web.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web.png~update the structure for gitbook
│   │   ├── 3.1.web2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web2.png~update the structure for gitbook
│   │   ├── 3.2.goweb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.2.goweb.png~update the structure for gitbook
│   │   ├── 3.3.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.http.png~update the structure for gitbook
│   │   ├── 3.3.illustrator.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.illustrator.png~update the structure for gitbook
│   │   ├── 4.1.login.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.login.png~update the structure for gitbook
│   │   ├── 4.1.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.slice.png~update the structure for gitbook
│   │   ├── 4.3.escape.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.3.escape.png~update the structure for gitbook
│   │   ├── 4.4.token.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.4.token.png~update the structure for gitbook
│   │   ├── 4.5.upload.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload.png~update the structure for gitbook
│   │   ├── 4.5.upload2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload2.png~update the structure for gitbook
│   │   ├── 5.6.mongodb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 5.6.mongodb.png~update the structure for gitbook
│   │   ├── 6.1.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie.png~update the structure for gitbook
│   │   ├── 6.1.cookie2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie2.png~update the structure for gitbook
│   │   ├── 6.1.session.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.session.png~update the structure for gitbook
│   │   ├── 6.4.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.cookie.png~update the structure for gitbook
│   │   ├── 6.4.hijack.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijack.png~update the structure for gitbook
│   │   ├── 6.4.hijacksuccess.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijacksuccess.png~update the structure for gitbook
│   │   ├── 6.4.setcookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.setcookie.png~update the structure for gitbook
│   │   ├── 7.4.template.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 7.4.template.png~update the structure for gitbook
│   │   ├── 8.1.socket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.1.socket.png~update the structure for gitbook
│   │   ├── 8.2.websocket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket.png~update the structure for gitbook
│   │   ├── 8.2.websocket2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket2.png~update the structure for gitbook
│   │   ├── 8.2.websocket3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket3.png~update the structure for gitbook
│   │   ├── 8.3.rest.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest.png~update the structure for gitbook
│   │   ├── 8.3.rest2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest2.png~update the structure for gitbook
│   │   ├── 8.3.rest3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest3.png~update the structure for gitbook
│   │   ├── 8.4.rpc.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.4.rpc.png~update the structure for gitbook
│   │   ├── 9.1.csrf.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 9.1.csrf.png~update the structure for gitbook
│   │   ├── cover.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── cover.png~update the structure for gitbook
│   │   ├── ebook.jpg~380a8ee74c41759d8189ad553423467994187253
│   │   ├── ebook.jpg~update the structure for gitbook
│   │   ├── navi1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi1.png~update the structure for gitbook
│   │   ├── navi10.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi10.png~update the structure for gitbook
│   │   ├── navi11.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi11.png~update the structure for gitbook
│   │   ├── navi12.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi12.png~update the structure for gitbook
│   │   ├── navi13.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi13.png~update the structure for gitbook
│   │   ├── navi14.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi14.png~update the structure for gitbook
│   │   ├── navi2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi2.png~update the structure for gitbook
│   │   ├── navi3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi3.png~update the structure for gitbook
│   │   ├── navi4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi4.png~update the structure for gitbook
│   │   ├── navi5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi5.png~update the structure for gitbook
│   │   ├── navi6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi6.png~update the structure for gitbook
│   │   ├── navi7.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi7.png~update the structure for gitbook
│   │   ├── navi8.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi8.png~update the structure for gitbook
│   │   ├── navi9.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi9.png~update the structure for gitbook
│   │   ├── polling.png~380a8ee74c41759d8189ad553423467994187253
│   │   └── polling.png~update the structure for gitbook
│   ├── preface.md
│   ├── ref.md
│   └── src/
│       └── 1.2/
│           ├── main.go
│           └── sqrt.go
├── es/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── README.md
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   └── ch.1.2/
│   │       │       └── main.go
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── preface.md
│   └── ref.md
├── fa/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── README.md
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── images/
│   │   ├── 1.1.cmd.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.cmd.png~update the structure for gitbook
│   │   ├── 1.1.linux.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.linux.png~update the structure for gitbook
│   │   ├── 1.1.mac.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.mac.png~update the structure for gitbook
│   │   ├── 1.3.go.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.3.go.png~update the structure for gitbook
│   │   ├── 1.4.eclipse1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse1.png~update the structure for gitbook
│   │   ├── 1.4.eclipse2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse2.png~update the structure for gitbook
│   │   ├── 1.4.eclipse3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse3.png~update the structure for gitbook
│   │   ├── 1.4.eclipse4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse4.png~update the structure for gitbook
│   │   ├── 1.4.eclipse5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse5.png~update the structure for gitbook
│   │   ├── 1.4.eclipse6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse6.png~update the structure for gitbook
│   │   ├── 1.4.emacs.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.emacs.png~update the structure for gitbook
│   │   ├── 1.4.idea1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea1.png~update the structure for gitbook
│   │   ├── 1.4.idea2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea2.png~update the structure for gitbook
│   │   ├── 1.4.idea3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea3.png~update the structure for gitbook
│   │   ├── 1.4.idea4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea4.png~update the structure for gitbook
│   │   ├── 1.4.idea5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea5.png~update the structure for gitbook
│   │   ├── 1.4.liteide.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.liteide.png~update the structure for gitbook
│   │   ├── 1.4.sublime1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime1.png~update the structure for gitbook
│   │   ├── 1.4.sublime2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime2.png~update the structure for gitbook
│   │   ├── 1.4.sublime3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime3.png~update the structure for gitbook
│   │   ├── 1.4.sublime4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime4.png~update the structure for gitbook
│   │   ├── 1.4.vim.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.vim.png~update the structure for gitbook
│   │   ├── 13.1.gopath.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath.png~update the structure for gitbook
│   │   ├── 13.1.gopath2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath2.png~update the structure for gitbook
│   │   ├── 13.4.beego.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.4.beego.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap2.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap3.png~update the structure for gitbook
│   │   ├── 14.4.github.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github.png~update the structure for gitbook
│   │   ├── 14.4.github2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github2.png~update the structure for gitbook
│   │   ├── 14.4.github3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github3.png~update the structure for gitbook
│   │   ├── 14.6.pprof.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof.png~update the structure for gitbook
│   │   ├── 14.6.pprof2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof2.png~update the structure for gitbook
│   │   ├── 14.6.pprof3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof3.png~update the structure for gitbook
│   │   ├── 2.2.array.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.array.png~update the structure for gitbook
│   │   ├── 2.2.basic.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.basic.png~update the structure for gitbook
│   │   ├── 2.2.makenew.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.makenew.png~update the structure for gitbook
│   │   ├── 2.2.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice.png~update the structure for gitbook
│   │   ├── 2.2.slice2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice2.png~update the structure for gitbook
│   │   ├── 2.3.init.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.3.init.png~update the structure for gitbook
│   │   ├── 2.4.student_struct.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.4.student_struct.png~update the structure for gitbook
│   │   ├── 2.5.rect_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.rect_func_without_receiver.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_without_receiver.png~update the structure for gitbook
│   │   ├── 3.1.dns2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns2.png~update the structure for gitbook
│   │   ├── 3.1.dns_hierachy.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_hierachy.png~update the structure for gitbook
│   │   ├── 3.1.dns_inquery.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_inquery.png~update the structure for gitbook
│   │   ├── 3.1.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.http.png~update the structure for gitbook
│   │   ├── 3.1.httpPOST.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.httpPOST.png~update the structure for gitbook
│   │   ├── 3.1.response.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.response.png~update the structure for gitbook
│   │   ├── 3.1.web.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web.png~update the structure for gitbook
│   │   ├── 3.1.web2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web2.png~update the structure for gitbook
│   │   ├── 3.2.goweb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.2.goweb.png~update the structure for gitbook
│   │   ├── 3.3.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.http.png~update the structure for gitbook
│   │   ├── 3.3.illustrator.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.illustrator.png~update the structure for gitbook
│   │   ├── 4.1.login.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.login.png~update the structure for gitbook
│   │   ├── 4.1.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.slice.png~update the structure for gitbook
│   │   ├── 4.3.escape.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.3.escape.png~update the structure for gitbook
│   │   ├── 4.4.token.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.4.token.png~update the structure for gitbook
│   │   ├── 4.5.upload.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload.png~update the structure for gitbook
│   │   ├── 4.5.upload2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload2.png~update the structure for gitbook
│   │   ├── 5.6.mongodb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 5.6.mongodb.png~update the structure for gitbook
│   │   ├── 6.1.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie.png~update the structure for gitbook
│   │   ├── 6.1.cookie2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie2.png~update the structure for gitbook
│   │   ├── 6.1.session.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.session.png~update the structure for gitbook
│   │   ├── 6.4.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.cookie.png~update the structure for gitbook
│   │   ├── 6.4.hijack.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijack.png~update the structure for gitbook
│   │   ├── 6.4.hijacksuccess.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijacksuccess.png~update the structure for gitbook
│   │   ├── 6.4.setcookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.setcookie.png~update the structure for gitbook
│   │   ├── 7.4.template.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 7.4.template.png~update the structure for gitbook
│   │   ├── 8.1.socket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.1.socket.png~update the structure for gitbook
│   │   ├── 8.2.websocket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket.png~update the structure for gitbook
│   │   ├── 8.2.websocket2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket2.png~update the structure for gitbook
│   │   ├── 8.2.websocket3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket3.png~update the structure for gitbook
│   │   ├── 8.3.rest.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest.png~update the structure for gitbook
│   │   ├── 8.3.rest2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest2.png~update the structure for gitbook
│   │   ├── 8.3.rest3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest3.png~update the structure for gitbook
│   │   ├── 8.4.rpc.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.4.rpc.png~update the structure for gitbook
│   │   ├── 9.1.csrf.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 9.1.csrf.png~update the structure for gitbook
│   │   ├── cover.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── cover.png~update the structure for gitbook
│   │   ├── ebook.jpg~380a8ee74c41759d8189ad553423467994187253
│   │   ├── ebook.jpg~update the structure for gitbook
│   │   ├── navi1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi1.png~update the structure for gitbook
│   │   ├── navi10.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi10.png~update the structure for gitbook
│   │   ├── navi11.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi11.png~update the structure for gitbook
│   │   ├── navi12.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi12.png~update the structure for gitbook
│   │   ├── navi13.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi13.png~update the structure for gitbook
│   │   ├── navi14.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi14.png~update the structure for gitbook
│   │   ├── navi2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi2.png~update the structure for gitbook
│   │   ├── navi3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi3.png~update the structure for gitbook
│   │   ├── navi4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi4.png~update the structure for gitbook
│   │   ├── navi5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi5.png~update the structure for gitbook
│   │   ├── navi6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi6.png~update the structure for gitbook
│   │   ├── navi7.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi7.png~update the structure for gitbook
│   │   ├── navi8.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi8.png~update the structure for gitbook
│   │   ├── navi9.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi9.png~update the structure for gitbook
│   │   ├── polling.png~380a8ee74c41759d8189ad553423467994187253
│   │   └── polling.png~update the structure for gitbook
│   ├── preface.md
│   └── ref.md
├── fr/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── preface.md
│   └── ref.md
├── ja/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── build.go
│   ├── build.sh
│   ├── config
│   ├── glossary.md
│   ├── images/
│   │   ├── alipay.png~380a8ee74c41759d8189ad553423467994187253
│   │   └── alipay.png~update the structure for gitbook
│   ├── preface.md
│   ├── ref.md
│   └── src/
│       └── 1.2/
│           ├── main.go
│           └── sqrt.go
├── pt-br/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── preface.md
│   └── ref.md
├── ru/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 06.0.md
│   └── preface.md
├── th/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── build.go
│   ├── build.sh
│   ├── code/
│   │   ├── readme.md
│   │   └── src/
│   │       ├── apps/
│   │       │   ├── ch.1.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.1/
│   │       │   │   └── main.go
│   │       │   ├── ch.2.2/
│   │       │   │   ├── main.go
│   │       │   │   └── what_is_wrong_with_this/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.3/
│   │       │   │   ├── basic_functions/
│   │       │   │   │   └── main.go
│   │       │   │   ├── hidden_print_methods/
│   │       │   │   │   └── main.go
│   │       │   │   ├── import_packages/
│   │       │   │   │   ├── main.go
│   │       │   │   │   └── only_call_init/
│   │       │   │   │       └── only_call_init.go
│   │       │   │   ├── main.go
│   │       │   │   ├── panic_and_recover/
│   │       │   │   │   └── main.go
│   │       │   │   ├── pass_by_value_and_pointer/
│   │       │   │   │   └── main.go
│   │       │   │   ├── type_function/
│   │       │   │   │   └── main.go
│   │       │   │   └── variadic_functions/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.4/
│   │       │   │   ├── compare_age/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs2/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_structs_with_name_conflict/
│   │       │   │   │   └── main.go
│   │       │   │   └── main.go
│   │       │   ├── ch.2.5/
│   │       │   │   ├── attach_methods_to_struct/
│   │       │   │   │   └── main.go
│   │       │   │   ├── box_example/
│   │       │   │   │   └── main.go
│   │       │   │   ├── embedded_method/
│   │       │   │   │   └── main.go
│   │       │   │   ├── method_overload/
│   │       │   │   │   └── main.go
│   │       │   │   └── pass_struct_to_method/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.6/
│   │       │   │   ├── interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── reflection/
│   │       │   │   │   └── main.go
│   │       │   │   ├── stringer_interface/
│   │       │   │   │   └── main.go
│   │       │   │   ├── switch_type_check/
│   │       │   │   │   └── main.go
│   │       │   │   └── type_check/
│   │       │   │       └── main.go
│   │       │   ├── ch.2.7/
│   │       │   │   ├── buffered_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── goroutine/
│   │       │   │   │   └── main.go
│   │       │   │   ├── range_and_close_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── select_channel/
│   │       │   │   │   └── main.go
│   │       │   │   ├── timeout/
│   │       │   │   │   └── main.go
│   │       │   │   └── unbuffered_channel/
│   │       │   │       └── main.go
│   │       │   ├── ch.3.2/
│   │       │   │   └── main.go
│   │       │   ├── ch.3.4/
│   │       │   │   └── main.go
│   │       │   ├── ch.4.1/
│   │       │   │   ├── login.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.3/
│   │       │   │   ├── index.gtpl
│   │       │   │   └── main.go
│   │       │   ├── ch.4.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── profile.gtpl
│   │       │   │   ├── submission.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.4.5/
│   │       │   │   ├── client_upload/
│   │       │   │   │   └── main.go
│   │       │   │   ├── index.gtpl
│   │       │   │   ├── main.go
│   │       │   │   ├── nonce/
│   │       │   │   │   └── main.go
│   │       │   │   ├── upload.gtpl
│   │       │   │   └── validator/
│   │       │   │       └── main.go
│   │       │   ├── ch.5.2/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.3/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.4/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   ├── ch.5.5/
│   │       │   │   ├── main.go
│   │       │   │   ├── readme.md
│   │       │   │   └── schema.sql
│   │       │   └── ch.5.6/
│   │       │       ├── mongodb/
│   │       │       │   ├── main.go
│   │       │       │   └── readme.md
│   │       │       └── redis/
│   │       │           ├── main.go
│   │       │           └── readme.md
│   │       └── mymath/
│   │           └── sqrt.go
│   ├── eBook/
│   │   ├── 05.0.md
│   │   └── 05.0.md.orig
│   ├── images/
│   │   ├── 1.1.cmd.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.cmd.png~update the structure for gitbook
│   │   ├── 1.1.linux.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.linux.png~update the structure for gitbook
│   │   ├── 1.1.mac.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.1.mac.png~update the structure for gitbook
│   │   ├── 1.3.go.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.3.go.png~update the structure for gitbook
│   │   ├── 1.4.eclipse1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse1.png~update the structure for gitbook
│   │   ├── 1.4.eclipse2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse2.png~update the structure for gitbook
│   │   ├── 1.4.eclipse3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse3.png~update the structure for gitbook
│   │   ├── 1.4.eclipse4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse4.png~update the structure for gitbook
│   │   ├── 1.4.eclipse5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse5.png~update the structure for gitbook
│   │   ├── 1.4.eclipse6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.eclipse6.png~update the structure for gitbook
│   │   ├── 1.4.emacs.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.emacs.png~update the structure for gitbook
│   │   ├── 1.4.idea1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea1.png~update the structure for gitbook
│   │   ├── 1.4.idea2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea2.png~update the structure for gitbook
│   │   ├── 1.4.idea3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea3.png~update the structure for gitbook
│   │   ├── 1.4.idea4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea4.png~update the structure for gitbook
│   │   ├── 1.4.idea5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.idea5.png~update the structure for gitbook
│   │   ├── 1.4.liteide.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.liteide.png~update the structure for gitbook
│   │   ├── 1.4.sublime1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime1.png~update the structure for gitbook
│   │   ├── 1.4.sublime2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime2.png~update the structure for gitbook
│   │   ├── 1.4.sublime3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime3.png~update the structure for gitbook
│   │   ├── 1.4.sublime4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.sublime4.png~update the structure for gitbook
│   │   ├── 1.4.vim.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 1.4.vim.png~update the structure for gitbook
│   │   ├── 13.1.gopath.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath.png~update the structure for gitbook
│   │   ├── 13.1.gopath2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.1.gopath2.png~update the structure for gitbook
│   │   ├── 13.4.beego.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 13.4.beego.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap2.png~update the structure for gitbook
│   │   ├── 14.1.bootstrap3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.1.bootstrap3.png~update the structure for gitbook
│   │   ├── 14.4.github.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github.png~update the structure for gitbook
│   │   ├── 14.4.github2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github2.png~update the structure for gitbook
│   │   ├── 14.4.github3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.4.github3.png~update the structure for gitbook
│   │   ├── 14.6.pprof.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof.png~update the structure for gitbook
│   │   ├── 14.6.pprof2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof2.png~update the structure for gitbook
│   │   ├── 14.6.pprof3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 14.6.pprof3.png~update the structure for gitbook
│   │   ├── 2.2.array.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.array.png~update the structure for gitbook
│   │   ├── 2.2.basic.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.basic.png~update the structure for gitbook
│   │   ├── 2.2.makenew.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.makenew.png~update the structure for gitbook
│   │   ├── 2.2.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice.png~update the structure for gitbook
│   │   ├── 2.2.slice2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.2.slice2.png~update the structure for gitbook
│   │   ├── 2.3.init.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.3.init.png~update the structure for gitbook
│   │   ├── 2.4.student_struct.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.4.student_struct.png~update the structure for gitbook
│   │   ├── 2.5.rect_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.rect_func_without_receiver.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_with_receiver_cp.png~update the structure for gitbook
│   │   ├── 2.5.shapes_func_without_receiver.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 2.5.shapes_func_without_receiver.png~update the structure for gitbook
│   │   ├── 3.1.dns2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns2.png~update the structure for gitbook
│   │   ├── 3.1.dns_hierachy.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_hierachy.png~update the structure for gitbook
│   │   ├── 3.1.dns_inquery.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.dns_inquery.png~update the structure for gitbook
│   │   ├── 3.1.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.http.png~update the structure for gitbook
│   │   ├── 3.1.httpPOST.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.httpPOST.png~update the structure for gitbook
│   │   ├── 3.1.response.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.response.png~update the structure for gitbook
│   │   ├── 3.1.web.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web.png~update the structure for gitbook
│   │   ├── 3.1.web2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.1.web2.png~update the structure for gitbook
│   │   ├── 3.2.goweb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.2.goweb.png~update the structure for gitbook
│   │   ├── 3.3.http.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.http.png~update the structure for gitbook
│   │   ├── 3.3.illustrator.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 3.3.illustrator.png~update the structure for gitbook
│   │   ├── 4.1.login.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.login.png~update the structure for gitbook
│   │   ├── 4.1.slice.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.1.slice.png~update the structure for gitbook
│   │   ├── 4.3.escape.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.3.escape.png~update the structure for gitbook
│   │   ├── 4.4.token.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.4.token.png~update the structure for gitbook
│   │   ├── 4.5.upload.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload.png~update the structure for gitbook
│   │   ├── 4.5.upload2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 4.5.upload2.png~update the structure for gitbook
│   │   ├── 5.6.mongodb.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 5.6.mongodb.png~update the structure for gitbook
│   │   ├── 6.1.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie.png~update the structure for gitbook
│   │   ├── 6.1.cookie2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.cookie2.png~update the structure for gitbook
│   │   ├── 6.1.session.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.1.session.png~update the structure for gitbook
│   │   ├── 6.4.cookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.cookie.png~update the structure for gitbook
│   │   ├── 6.4.hijack.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijack.png~update the structure for gitbook
│   │   ├── 6.4.hijacksuccess.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.hijacksuccess.png~update the structure for gitbook
│   │   ├── 6.4.setcookie.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 6.4.setcookie.png~update the structure for gitbook
│   │   ├── 7.4.template.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 7.4.template.png~update the structure for gitbook
│   │   ├── 8.1.socket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.1.socket.png~update the structure for gitbook
│   │   ├── 8.2.websocket.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket.png~update the structure for gitbook
│   │   ├── 8.2.websocket2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket2.png~update the structure for gitbook
│   │   ├── 8.2.websocket3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.2.websocket3.png~update the structure for gitbook
│   │   ├── 8.3.rest.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest.png~update the structure for gitbook
│   │   ├── 8.3.rest2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest2.png~update the structure for gitbook
│   │   ├── 8.3.rest3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.3.rest3.png~update the structure for gitbook
│   │   ├── 8.4.rpc.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 8.4.rpc.png~update the structure for gitbook
│   │   ├── 9.1.csrf.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── 9.1.csrf.png~update the structure for gitbook
│   │   ├── cover.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── cover.png~update the structure for gitbook
│   │   ├── ebook.jpg~380a8ee74c41759d8189ad553423467994187253
│   │   ├── ebook.jpg~update the structure for gitbook
│   │   ├── navi1.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi1.png~update the structure for gitbook
│   │   ├── navi10.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi10.png~update the structure for gitbook
│   │   ├── navi11.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi11.png~update the structure for gitbook
│   │   ├── navi12.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi12.png~update the structure for gitbook
│   │   ├── navi13.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi13.png~update the structure for gitbook
│   │   ├── navi14.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi14.png~update the structure for gitbook
│   │   ├── navi2.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi2.png~update the structure for gitbook
│   │   ├── navi3.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi3.png~update the structure for gitbook
│   │   ├── navi4.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi4.png~update the structure for gitbook
│   │   ├── navi5.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi5.png~update the structure for gitbook
│   │   ├── navi6.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi6.png~update the structure for gitbook
│   │   ├── navi7.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi7.png~update the structure for gitbook
│   │   ├── navi8.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi8.png~update the structure for gitbook
│   │   ├── navi9.png~380a8ee74c41759d8189ad553423467994187253
│   │   ├── navi9.png~update the structure for gitbook
│   │   ├── polling.png~380a8ee74c41759d8189ad553423467994187253
│   │   └── polling.png~update the structure for gitbook
│   ├── preface.md
│   ├── ref.md
│   └── src/
│       └── 1.2/
│           ├── main.go
│           └── sqrt.go
├── tr/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── README.md
│   └── preface.md
├── zh/
│   ├── 01.0.md
│   ├── 01.1.md
│   ├── 01.2.md
│   ├── 01.3.md
│   ├── 01.4.md
│   ├── 01.5.md
│   ├── 02.0.md
│   ├── 02.1.md
│   ├── 02.2.md
│   ├── 02.3.md
│   ├── 02.4.md
│   ├── 02.5.md
│   ├── 02.6.md
│   ├── 02.7.md
│   ├── 02.8.md
│   ├── 03.0.md
│   ├── 03.1.md
│   ├── 03.2.md
│   ├── 03.3.md
│   ├── 03.4.md
│   ├── 03.5.md
│   ├── 04.0.md
│   ├── 04.1.md
│   ├── 04.2.md
│   ├── 04.3.md
│   ├── 04.4.md
│   ├── 04.5.md
│   ├── 04.6.md
│   ├── 05.0.md
│   ├── 05.1.md
│   ├── 05.2.md
│   ├── 05.3.md
│   ├── 05.4.md
│   ├── 05.5.md
│   ├── 05.6.md
│   ├── 05.7.md
│   ├── 06.0.md
│   ├── 06.1.md
│   ├── 06.2.md
│   ├── 06.3.md
│   ├── 06.4.md
│   ├── 06.5.md
│   ├── 07.0.md
│   ├── 07.1.md
│   ├── 07.2.md
│   ├── 07.3.md
│   ├── 07.4.md
│   ├── 07.5.md
│   ├── 07.6.md
│   ├── 07.7.md
│   ├── 08.0.md
│   ├── 08.1.md
│   ├── 08.2.md
│   ├── 08.3.md
│   ├── 08.4.md
│   ├── 08.5.md
│   ├── 09.0.md
│   ├── 09.1.md
│   ├── 09.2.md
│   ├── 09.3.md
│   ├── 09.4.md
│   ├── 09.5.md
│   ├── 09.6.md
│   ├── 09.7.md
│   ├── 10.0.md
│   ├── 10.1.md
│   ├── 10.2.md
│   ├── 10.3.md
│   ├── 10.4.md
│   ├── 11.0.md
│   ├── 11.1.md
│   ├── 11.2.md
│   ├── 11.3.md
│   ├── 11.4.md
│   ├── 12.0.md
│   ├── 12.1.md
│   ├── 12.2.md
│   ├── 12.3.md
│   ├── 12.4.md
│   ├── 12.5.md
│   ├── 13.0.md
│   ├── 13.1.md
│   ├── 13.2.md
│   ├── 13.3.md
│   ├── 13.4.md
│   ├── 13.5.md
│   ├── 13.6.md
│   ├── 14.0.md
│   ├── 14.1.md
│   ├── 14.2.md
│   ├── 14.3.md
│   ├── 14.4.md
│   ├── 14.5.md
│   ├── 14.6.md
│   ├── 14.7.md
│   ├── README.md
│   ├── SUMMARY.md
│   ├── a_herf.go
│   ├── a_href.py
│   ├── build-web-application-with-golang.azw3
│   ├── build.go
│   ├── build.sh
│   ├── build_new.go
│   ├── build_new.sh
│   ├── preface.md
│   ├── ref.md
│   └── src/
│       └── 1.2/
│           ├── main.go~HEAD
│           ├── main.go~eead24cf064976b648de5826eab51880c803b0fa
│           ├── sqrt.go~HEAD
│           └── sqrt.go~eead24cf064976b648de5826eab51880c803b0fa
└── zh-tw/
    ├── 01.0.md
    ├── 01.1.md
    ├── 01.2.md
    ├── 01.3.md
    ├── 01.4.md
    ├── 01.5.md
    ├── 02.0.md
    ├── 02.1.md
    ├── 02.2.md
    ├── 02.3.md
    ├── 02.4.md
    ├── 02.5.md
    ├── 02.6.md
    ├── 02.7.md
    ├── 02.8.md
    ├── 03.0.md
    ├── 03.1.md
    ├── 03.2.md
    ├── 03.3.md
    ├── 03.4.md
    ├── 03.5.md
    ├── 04.0.md
    ├── 04.1.md
    ├── 04.2.md
    ├── 04.3.md
    ├── 04.4.md
    ├── 04.5.md
    ├── 04.6.md
    ├── 05.0.md
    ├── 05.1.md
    ├── 05.2.md
    ├── 05.3.md
    ├── 05.4.md
    ├── 05.5.md
    ├── 05.6.md
    ├── 05.7.md
    ├── 06.0.md
    ├── 06.1.md
    ├── 06.2.md
    ├── 06.3.md
    ├── 06.4.md
    ├── 06.5.md
    ├── 07.0.md
    ├── 07.1.md
    ├── 07.2.md
    ├── 07.3.md
    ├── 07.4.md
    ├── 07.5.md
    ├── 07.6.md
    ├── 07.7.md
    ├── 08.0.md
    ├── 08.1.md
    ├── 08.2.md
    ├── 08.3.md
    ├── 08.4.md
    ├── 08.5.md
    ├── 09.0.md
    ├── 09.1.md
    ├── 09.2.md
    ├── 09.3.md
    ├── 09.4.md
    ├── 09.5.md
    ├── 09.6.md
    ├── 09.7.md
    ├── 10.0.md
    ├── 10.1.md
    ├── 10.2.md
    ├── 10.3.md
    ├── 10.4.md
    ├── 11.0.md
    ├── 11.1.md
    ├── 11.2.md
    ├── 11.3.md
    ├── 11.4.md
    ├── 12.0.md
    ├── 12.1.md
    ├── 12.2.md
    ├── 12.3.md
    ├── 12.4.md
    ├── 12.5.md
    ├── 13.0.md
    ├── 13.1.md
    ├── 13.2.md
    ├── 13.3.md
    ├── 13.4.md
    ├── 13.5.md
    ├── 13.6.md
    ├── 14.0.md
    ├── 14.1.md
    ├── 14.2.md
    ├── 14.3.md
    ├── 14.4.md
    ├── 14.5.md
    ├── 14.6.md
    ├── 14.7.md
    ├── README.md
    ├── SUMMARY.md
    ├── a_herf.go
    ├── a_href.py
    ├── build-web-application-with-golang.azw3
    ├── build.go
    ├── build.sh
    ├── build_new.go
    ├── build_new.sh
    ├── preface.md
    ├── ref.md
    └── src/
        └── 1.2/
            ├── main.go
            └── sqrt.go
Download .txt
SYMBOL INDEX (1472 symbols across 309 files)

FILE: de/code/src/apps/ch.1.2/main.go
  function main (line 12) | func main() {

FILE: de/code/src/apps/ch.2.1/main.go
  function main (line 9) | func main() {

FILE: de/code/src/apps/ch.2.2/main.go
  constant Pi (line 11) | Pi = 3.1415926
  constant i (line 19) | i         = 1e4
  constant MaxThread (line 20) | MaxThread = 10
  constant prefix (line 21) | prefix    = "astaxie_"
  function show_multiple_assignments (line 29) | func show_multiple_assignments() {
  function show_bool (line 49) | func show_bool() {
  function show_different_types (line 58) | func show_different_types() {
  function show_strings (line 79) | func show_strings() {
  function show_string_manipulation (line 93) | func show_string_manipulation() {
  function show_errors (line 115) | func show_errors() {
  function show_iota (line 122) | func show_iota() {
  function This_is_public (line 145) | func This_is_public()  {}
  function this_is_private (line 146) | func this_is_private() {}
  function set_default_values (line 148) | func set_default_values() {
  function show_arrays (line 164) | func show_arrays() {
  function show_slices (line 196) | func show_slices() {
  function show_map (line 237) | func show_map() {
  function main (line 265) | func main() {

FILE: de/code/src/apps/ch.2.2/what_is_wrong_with_this/main.go
  function main (line 6) | func main() {

FILE: de/code/src/apps/ch.2.3/basic_functions/main.go
  function max (line 8) | func max(a, b int) int {
  function main (line 15) | func main() {

FILE: de/code/src/apps/ch.2.3/hidden_print_methods/main.go
  function f (line 7) | func f() {
  function main (line 12) | func main() {

FILE: de/code/src/apps/ch.2.3/import_packages/main.go
  function main (line 20) | func main() {

FILE: de/code/src/apps/ch.2.3/import_packages/only_call_init/only_call_init.go
  function init (line 5) | func init() {

FILE: de/code/src/apps/ch.2.3/main.go
  function computedValue (line 7) | func computedValue() int {
  function show_if (line 10) | func show_if() {
  function show_if_var (line 31) | func show_if_var() {
  function show_goto (line 43) | func show_goto() {
  function show_for_loop (line 54) | func show_for_loop() {
  function show_loop_through_map (line 78) | func show_loop_through_map() {
  function show_switch (line 91) | func show_switch() {
  function show_defer (line 127) | func show_defer() {
  function main (line 134) | func main() {

FILE: de/code/src/apps/ch.2.3/panic_and_recover/main.go
  function check_user (line 12) | func check_user() {
  function throwsPanic (line 18) | func throwsPanic(f func()) (b bool) {
  function main (line 28) | func main(){

FILE: de/code/src/apps/ch.2.3/pass_by_value_and_pointer/main.go
  function add_by_value (line 7) | func add_by_value(a int) int {
  function add_by_reference (line 11) | func add_by_reference(a *int) int {
  function show_add_by_value (line 15) | func show_add_by_value() {
  function show_add_by_reference (line 21) | func show_add_by_reference() {
  function main (line 28) | func main() {

FILE: de/code/src/apps/ch.2.3/type_function/main.go
  type testInt (line 7) | type testInt
  function isOdd (line 9) | func isOdd(integer int) bool {
  function isEven (line 16) | func isEven(integer int) bool {
  function filter (line 25) | func filter(slice []int, f testInt) []int {
  function init (line 34) | func init() {
  function main (line 37) | func main() {

FILE: de/code/src/apps/ch.2.3/variadic_functions/main.go
  function SumAndProduct (line 8) | func SumAndProduct(A, B int) (int, int) {
  function main (line 12) | func main() {

FILE: de/code/src/apps/ch.2.4/compare_age/main.go
  type person (line 8) | type person struct
  function Older (line 15) | func Older(p1, p2 person) (person, int) {
  function main (line 22) | func main() {

FILE: de/code/src/apps/ch.2.4/embedded_structs/main.go
  type Human (line 7) | type Human struct
  type Student (line 13) | type Student struct
  function main (line 18) | func main() {

FILE: de/code/src/apps/ch.2.4/embedded_structs2/main.go
  type Skills (line 7) | type Skills
  type Human (line 9) | type Human struct
  type Student (line 15) | type Student struct
  function main (line 22) | func main() {

FILE: de/code/src/apps/ch.2.4/embedded_structs_with_name_conflict/main.go
  type Human (line 7) | type Human struct
  type Employee (line 13) | type Employee struct
  function main (line 19) | func main() {

FILE: de/code/src/apps/ch.2.4/main.go
  function show_basic_struct (line 7) | func show_basic_struct() {
  function show_anonymous_struct (line 27) | func show_anonymous_struct() {
  function main (line 36) | func main() {

FILE: de/code/src/apps/ch.2.5/attach_methods_to_struct/main.go
  type Rectangle (line 10) | type Rectangle struct
    method area (line 18) | func (r Rectangle) area() float64 {
  type Circle (line 14) | type Circle struct
    method area (line 22) | func (c Circle) area() float64 {
  function main (line 26) | func main() {

FILE: de/code/src/apps/ch.2.5/box_example/main.go
  constant WHITE (line 6) | WHITE = iota
  constant BLACK (line 7) | BLACK
  constant BLUE (line 8) | BLUE
  constant RED (line 9) | RED
  constant YELLOW (line 10) | YELLOW
  type Color (line 13) | type Color
    method String (line 48) | func (c Color) String() string {
  type Box (line 15) | type Box struct
    method Volume (line 22) | func (b Box) Volume() float64 {
    method SetColor (line 26) | func (b *Box) SetColor(c Color) {
  type BoxList (line 20) | type BoxList
    method BiggestsColor (line 30) | func (bl BoxList) BiggestsColor() Color {
    method PaintItBlack (line 42) | func (bl BoxList) PaintItBlack() {
  function main (line 53) | func main() {

FILE: de/code/src/apps/ch.2.5/embedded_method/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 10) | type Student struct
  type Employee (line 15) | type Employee struct
  function main (line 25) | func main() {

FILE: de/code/src/apps/ch.2.5/method_overload/main.go
  type Human (line 5) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 11) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 25) | func (e *Employee) SayHi() {
  function main (line 30) | func main() {

FILE: de/code/src/apps/ch.2.5/pass_struct_to_method/main.go
  type Rectangle (line 5) | type Rectangle struct
  function area (line 9) | func area(r Rectangle) float64 {
  function main (line 13) | func main() {

FILE: de/code/src/apps/ch.2.6/interface/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 22) | func (h Human) SayHi() {
    method Sing (line 26) | func (h Human) Sing(lyrics string) {
  type Student (line 10) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 30) | func (e Employee) SayHi() {
  type Men (line 36) | type Men interface
  function main (line 41) | func main() {

FILE: de/code/src/apps/ch.2.6/reflection/main.go
  function show_interface_none (line 8) | func show_interface_none() {
  function show_reflection (line 16) | func show_reflection() {
  function main (line 30) | func main() {

FILE: de/code/src/apps/ch.2.6/stringer_interface/main.go
  type Human (line 8) | type Human struct
    method String (line 15) | func (h Human) String() string {
  function main (line 19) | func main() {

FILE: de/code/src/apps/ch.2.6/switch_type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: de/code/src/apps/ch.2.6/type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: de/code/src/apps/ch.2.7/buffered_channel/main.go
  function main (line 7) | func main() {

FILE: de/code/src/apps/ch.2.7/goroutine/main.go
  function say (line 10) | func say(s string) {
  function main (line 17) | func main() {

FILE: de/code/src/apps/ch.2.7/range_and_close_channel/main.go
  function fibonacci (line 9) | func fibonacci(n int, c chan int) {
  function main (line 18) | func main() {

FILE: de/code/src/apps/ch.2.7/select_channel/main.go
  function fibonacci (line 7) | func fibonacci(c, quit chan int) {
  function main (line 20) | func main() {

FILE: de/code/src/apps/ch.2.7/timeout/main.go
  function main (line 11) | func main() {

FILE: de/code/src/apps/ch.2.7/unbuffered_channel/main.go
  function sum (line 7) | func sum(a []int, c chan int) {
  function main (line 15) | func main() {

FILE: de/code/src/apps/ch.3.2/main.go
  function sayhelloName (line 12) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 25) | func main() {

FILE: de/code/src/apps/ch.3.4/main.go
  type MyMux (line 11) | type MyMux struct
    method ServeHTTP (line 14) | func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  function sayhelloName (line 23) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 27) | func main() {

FILE: de/code/src/apps/ch.4.1/main.go
  function sayhelloName (line 14) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function login (line 28) | func login(w http.ResponseWriter, r *http.Request) {
  function main (line 41) | func main() {

FILE: de/code/src/apps/ch.4.2/main.go
  constant PORT (line 15) | PORT     = "9090"
  constant HOST_URL (line 16) | HOST_URL = "http://localhost:" + PORT
  type Links (line 21) | type Links struct
  function index (line 28) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 31) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 34) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 50) | func main() {

FILE: de/code/src/apps/ch.4.2/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: de/code/src/apps/ch.4.3/main.go
  function index (line 13) | func index(w http.ResponseWriter, r *http.Request) {
  function templateHandler (line 23) | func templateHandler(w http.ResponseWriter, r *http.Request) {
  function main (line 35) | func main() {

FILE: de/code/src/apps/ch.4.4/main.go
  constant PORT (line 16) | PORT     = "9090"
  constant HOST_URL (line 17) | HOST_URL = "http://localhost:" + PORT
  function index (line 23) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 26) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 29) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 45) | func main() {

FILE: de/code/src/apps/ch.4.4/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: de/code/src/apps/ch.4.4/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: de/code/src/apps/ch.4.5/client_upload/main.go
  function checkError (line 13) | func checkError(err error) {
  function postFile (line 18) | func postFile(filename string, targetUrl string) {
  function main (line 42) | func main() {

FILE: de/code/src/apps/ch.4.5/main.go
  constant MiB_UNIT (line 16) | MiB_UNIT = 1 << 20
  function checkError (line 21) | func checkError(err error) {
  function indexHandler (line 26) | func indexHandler(w http.ResponseWriter, r *http.Request) {
  function uploadHandler (line 30) | func uploadHandler(w http.ResponseWriter, r *http.Request) {
  function saveUpload (line 44) | func saveUpload(file multipart.File, handler *multipart.FileHeader) {
  function init (line 54) | func init() {
  function main (line 59) | func main() {

FILE: de/code/src/apps/ch.4.5/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: de/code/src/apps/ch.4.5/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: de/code/src/apps/ch.5.2/main.go
  constant DB_USER (line 12) | DB_USER     = "user"
  constant DB_PASSWORD (line 13) | DB_PASSWORD = ""
  constant DB_NAME (line 14) | DB_NAME     = "test"
  function main (line 17) | func main() {
  function checkErr (line 72) | func checkErr(err error) {

FILE: de/code/src/apps/ch.5.2/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: de/code/src/apps/ch.5.3/main.go
  constant DB_PATH (line 12) | DB_PATH = "./foo.db"
  function main (line 14) | func main() {
  function checkErr (line 68) | func checkErr(err error) {

FILE: de/code/src/apps/ch.5.3/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: de/code/src/apps/ch.5.4/main.go
  constant DB_USER (line 14) | DB_USER     = "user"
  constant DB_PASSWORD (line 15) | DB_PASSWORD = ""
  constant DB_NAME (line 16) | DB_NAME     = "test"
  function main (line 19) | func main() {
  function checkErr (line 74) | func checkErr(err error) {

FILE: de/code/src/apps/ch.5.4/schema.sql
  type userinfo (line 1) | CREATE TABLE userinfo

FILE: de/code/src/apps/ch.5.5/main.go
  type Userinfo (line 15) | type Userinfo struct
  constant DB_PATH (line 22) | DB_PATH = "./foo.db"
  function checkError (line 24) | func checkError(err error) {
  function getTimeStamp (line 29) | func getTimeStamp() string {
  function insertUsingStruct (line 32) | func insertUsingStruct() int64 {
  function insertUsingMap (line 42) | func insertUsingMap() int64 {
  function getOneUserInfo (line 54) | func getOneUserInfo(id int64) Userinfo {
  function getAllUserInfo (line 61) | func getAllUserInfo(id int64) []Userinfo {
  function updateUserinfo (line 68) | func updateUserinfo(id int64) {
  function updateUsingMap (line 79) | func updateUsingMap(id int64) {
  function getMapsFromSelect (line 91) | func getMapsFromSelect(id int64) []map[string][]byte {
  function groupby (line 101) | func groupby() {
  function joinTables (line 109) | func joinTables(id int64) {
  function deleteWithUserinfo (line 117) | func deleteWithUserinfo(id int64) {
  function deleteRows (line 125) | func deleteRows() {
  function deleteAllUserinfo (line 133) | func deleteAllUserinfo(id int64) {
  function main (line 141) | func main() {

FILE: de/code/src/apps/ch.5.5/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (
  type `userdetail` (line 7) | CREATE TABLE `userdetail` (

FILE: de/code/src/apps/ch.5.6/mongodb/main.go
  type Person (line 11) | type Person struct
  function checkError (line 16) | func checkError(err error) {
  constant DB_NAME (line 23) | DB_NAME       = "test"
  constant DB_COLLECTION (line 24) | DB_COLLECTION = "people"
  function main (line 27) | func main() {

FILE: de/code/src/apps/ch.5.6/redis/main.go
  function checkError (line 10) | func checkError(err error) {
  constant DB_PORT (line 17) | DB_PORT = "9191"
  constant DB_URL (line 18) | DB_URL  = "127.0.0.1"
  function main (line 21) | func main() {

FILE: de/code/src/mymath/sqrt.go
  function Sqrt (line 6) | func Sqrt(x float64) float64 {

FILE: en/build.go
  type Visitor (line 15) | type Visitor struct
    method md2html (line 17) | func (self *Visitor) md2html(arg map[string]string) error {
  function FixHeader (line 77) | func FixHeader(input string) string {
  function RemoveFooterLink (line 87) | func RemoveFooterLink(input string) string {
  function RemoveImageLinkSuffix (line 92) | func RemoveImageLinkSuffix(input string) string {
  function main (line 97) | func main() {

FILE: en/code/src/apps/ch.1.2/main.go
  function main (line 12) | func main() {

FILE: en/code/src/apps/ch.2.1/main.go
  function main (line 9) | func main() {

FILE: en/code/src/apps/ch.2.2/main.go
  constant Pi (line 11) | Pi = 3.1415926
  constant i (line 19) | i         = 1e4
  constant MaxThread (line 20) | MaxThread = 10
  constant prefix (line 21) | prefix    = "astaxie_"
  function show_multiple_assignments (line 29) | func show_multiple_assignments() {
  function show_bool (line 49) | func show_bool() {
  function show_different_types (line 58) | func show_different_types() {
  function show_strings (line 79) | func show_strings() {
  function show_string_manipulation (line 93) | func show_string_manipulation() {
  function show_errors (line 115) | func show_errors() {
  function show_iota (line 122) | func show_iota() {
  function This_is_public (line 145) | func This_is_public()  {}
  function this_is_private (line 146) | func this_is_private() {}
  function set_default_values (line 148) | func set_default_values() {
  function show_arrays (line 164) | func show_arrays() {
  function show_slices (line 196) | func show_slices() {
  function show_map (line 237) | func show_map() {
  function main (line 265) | func main() {

FILE: en/code/src/apps/ch.2.2/what_is_wrong_with_this/main.go
  function main (line 6) | func main() {

FILE: en/code/src/apps/ch.2.3/basic_functions/main.go
  function max (line 8) | func max(a, b int) int {
  function main (line 15) | func main() {

FILE: en/code/src/apps/ch.2.3/hidden_print_methods/main.go
  function f (line 7) | func f() {
  function main (line 12) | func main() {

FILE: en/code/src/apps/ch.2.3/import_packages/main.go
  function main (line 20) | func main() {

FILE: en/code/src/apps/ch.2.3/import_packages/only_call_init/only_call_init.go
  function init (line 5) | func init() {

FILE: en/code/src/apps/ch.2.3/main.go
  function computedValue (line 7) | func computedValue() int {
  function show_if (line 10) | func show_if() {
  function show_if_var (line 31) | func show_if_var() {
  function show_goto (line 43) | func show_goto() {
  function show_for_loop (line 54) | func show_for_loop() {
  function show_loop_through_map (line 78) | func show_loop_through_map() {
  function show_switch (line 91) | func show_switch() {
  function show_defer (line 127) | func show_defer() {
  function main (line 134) | func main() {

FILE: en/code/src/apps/ch.2.3/panic_and_recover/main.go
  function check_user (line 12) | func check_user() {
  function throwsPanic (line 18) | func throwsPanic(f func()) (b bool) {
  function main (line 28) | func main(){

FILE: en/code/src/apps/ch.2.3/pass_by_value_and_pointer/main.go
  function add_by_value (line 7) | func add_by_value(a int) int {
  function add_by_reference (line 11) | func add_by_reference(a *int) int {
  function show_add_by_value (line 15) | func show_add_by_value() {
  function show_add_by_reference (line 21) | func show_add_by_reference() {
  function main (line 28) | func main() {

FILE: en/code/src/apps/ch.2.3/type_function/main.go
  type testInt (line 7) | type testInt
  function isOdd (line 9) | func isOdd(integer int) bool {
  function isEven (line 16) | func isEven(integer int) bool {
  function filter (line 25) | func filter(slice []int, f testInt) []int {
  function init (line 34) | func init() {
  function main (line 37) | func main() {

FILE: en/code/src/apps/ch.2.3/variadic_functions/main.go
  function SumAndProduct (line 8) | func SumAndProduct(A, B int) (int, int) {
  function main (line 12) | func main() {

FILE: en/code/src/apps/ch.2.4/compare_age/main.go
  type person (line 8) | type person struct
  function Older (line 15) | func Older(p1, p2 person) (person, int) {
  function main (line 22) | func main() {

FILE: en/code/src/apps/ch.2.4/embedded_structs/main.go
  type Human (line 7) | type Human struct
  type Student (line 13) | type Student struct
  function main (line 18) | func main() {

FILE: en/code/src/apps/ch.2.4/embedded_structs2/main.go
  type Skills (line 7) | type Skills
  type Human (line 9) | type Human struct
  type Student (line 15) | type Student struct
  function main (line 22) | func main() {

FILE: en/code/src/apps/ch.2.4/embedded_structs_with_name_conflict/main.go
  type Human (line 7) | type Human struct
  type Employee (line 13) | type Employee struct
  function main (line 19) | func main() {

FILE: en/code/src/apps/ch.2.4/main.go
  function show_basic_struct (line 7) | func show_basic_struct() {
  function show_anonymous_struct (line 27) | func show_anonymous_struct() {
  function main (line 36) | func main() {

FILE: en/code/src/apps/ch.2.5/attach_methods_to_struct/main.go
  type Rectangle (line 10) | type Rectangle struct
    method area (line 18) | func (r Rectangle) area() float64 {
  type Circle (line 14) | type Circle struct
    method area (line 22) | func (c Circle) area() float64 {
  function main (line 26) | func main() {

FILE: en/code/src/apps/ch.2.5/box_example/main.go
  constant WHITE (line 6) | WHITE = iota
  constant BLACK (line 7) | BLACK
  constant BLUE (line 8) | BLUE
  constant RED (line 9) | RED
  constant YELLOW (line 10) | YELLOW
  type Color (line 13) | type Color
    method String (line 48) | func (c Color) String() string {
  type Box (line 15) | type Box struct
    method Volume (line 22) | func (b Box) Volume() float64 {
    method SetColor (line 26) | func (b *Box) SetColor(c Color) {
  type BoxList (line 20) | type BoxList
    method BiggestsColor (line 30) | func (bl BoxList) BiggestsColor() Color {
    method PaintItBlack (line 42) | func (bl BoxList) PaintItBlack() {
  function main (line 53) | func main() {

FILE: en/code/src/apps/ch.2.5/embedded_method/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 10) | type Student struct
  type Employee (line 15) | type Employee struct
  function main (line 25) | func main() {

FILE: en/code/src/apps/ch.2.5/method_overload/main.go
  type Human (line 5) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 11) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 25) | func (e *Employee) SayHi() {
  function main (line 30) | func main() {

FILE: en/code/src/apps/ch.2.5/pass_struct_to_method/main.go
  type Rectangle (line 5) | type Rectangle struct
  function area (line 9) | func area(r Rectangle) float64 {
  function main (line 13) | func main() {

FILE: en/code/src/apps/ch.2.6/interface/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 22) | func (h Human) SayHi() {
    method Sing (line 26) | func (h Human) Sing(lyrics string) {
  type Student (line 10) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 30) | func (e Employee) SayHi() {
  type Men (line 36) | type Men interface
  function main (line 41) | func main() {

FILE: en/code/src/apps/ch.2.6/reflection/main.go
  function show_interface_none (line 8) | func show_interface_none() {
  function show_reflection (line 16) | func show_reflection() {
  function main (line 30) | func main() {

FILE: en/code/src/apps/ch.2.6/stringer_interface/main.go
  type Human (line 8) | type Human struct
    method String (line 15) | func (h Human) String() string {
  function main (line 19) | func main() {

FILE: en/code/src/apps/ch.2.6/switch_type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: en/code/src/apps/ch.2.6/type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: en/code/src/apps/ch.2.7/buffered_channel/main.go
  function main (line 7) | func main() {

FILE: en/code/src/apps/ch.2.7/goroutine/main.go
  function say (line 10) | func say(s string) {
  function main (line 17) | func main() {

FILE: en/code/src/apps/ch.2.7/range_and_close_channel/main.go
  function fibonacci (line 9) | func fibonacci(n int, c chan int) {
  function main (line 18) | func main() {

FILE: en/code/src/apps/ch.2.7/select_channel/main.go
  function fibonacci (line 7) | func fibonacci(c, quit chan int) {
  function main (line 20) | func main() {

FILE: en/code/src/apps/ch.2.7/timeout/main.go
  function main (line 11) | func main() {

FILE: en/code/src/apps/ch.2.7/unbuffered_channel/main.go
  function sum (line 7) | func sum(a []int, c chan int) {
  function main (line 15) | func main() {

FILE: en/code/src/apps/ch.3.2/main.go
  function sayhelloName (line 12) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 25) | func main() {

FILE: en/code/src/apps/ch.3.4/main.go
  type MyMux (line 11) | type MyMux struct
    method ServeHTTP (line 14) | func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  function sayhelloName (line 23) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 27) | func main() {

FILE: en/code/src/apps/ch.4.1/main.go
  function sayhelloName (line 14) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function login (line 28) | func login(w http.ResponseWriter, r *http.Request) {
  function main (line 41) | func main() {

FILE: en/code/src/apps/ch.4.2/main.go
  constant PORT (line 15) | PORT     = "9090"
  constant HOST_URL (line 16) | HOST_URL = "http://localhost:" + PORT
  type Links (line 21) | type Links struct
  function index (line 28) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 31) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 34) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 50) | func main() {

FILE: en/code/src/apps/ch.4.2/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: en/code/src/apps/ch.4.3/main.go
  function index (line 13) | func index(w http.ResponseWriter, r *http.Request) {
  function templateHandler (line 23) | func templateHandler(w http.ResponseWriter, r *http.Request) {
  function main (line 35) | func main() {

FILE: en/code/src/apps/ch.4.4/main.go
  constant PORT (line 16) | PORT     = "9090"
  constant HOST_URL (line 17) | HOST_URL = "http://localhost:" + PORT
  function index (line 23) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 26) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 29) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 45) | func main() {

FILE: en/code/src/apps/ch.4.4/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: en/code/src/apps/ch.4.4/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: en/code/src/apps/ch.4.5/client_upload/main.go
  function checkError (line 13) | func checkError(err error) {
  function postFile (line 18) | func postFile(filename string, targetUrl string) {
  function main (line 42) | func main() {

FILE: en/code/src/apps/ch.4.5/main.go
  constant MiB_UNIT (line 16) | MiB_UNIT = 1 << 20
  function checkError (line 21) | func checkError(err error) {
  function indexHandler (line 26) | func indexHandler(w http.ResponseWriter, r *http.Request) {
  function uploadHandler (line 30) | func uploadHandler(w http.ResponseWriter, r *http.Request) {
  function saveUpload (line 44) | func saveUpload(file multipart.File, handler *multipart.FileHeader) {
  function init (line 54) | func init() {
  function main (line 59) | func main() {

FILE: en/code/src/apps/ch.4.5/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: en/code/src/apps/ch.4.5/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: en/code/src/apps/ch.5.2/main.go
  constant DB_USER (line 12) | DB_USER     = "user"
  constant DB_PASSWORD (line 13) | DB_PASSWORD = ""
  constant DB_NAME (line 14) | DB_NAME     = "test"
  function main (line 17) | func main() {
  function checkErr (line 72) | func checkErr(err error) {

FILE: en/code/src/apps/ch.5.2/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: en/code/src/apps/ch.5.3/main.go
  constant DB_PATH (line 12) | DB_PATH = "./foo.db"
  function main (line 14) | func main() {
  function checkErr (line 68) | func checkErr(err error) {

FILE: en/code/src/apps/ch.5.3/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: en/code/src/apps/ch.5.4/main.go
  constant DB_USER (line 14) | DB_USER     = "user"
  constant DB_PASSWORD (line 15) | DB_PASSWORD = ""
  constant DB_NAME (line 16) | DB_NAME     = "test"
  function main (line 19) | func main() {
  function checkErr (line 74) | func checkErr(err error) {

FILE: en/code/src/apps/ch.5.4/schema.sql
  type userinfo (line 1) | CREATE TABLE userinfo

FILE: en/code/src/apps/ch.5.5/main.go
  type Userinfo (line 15) | type Userinfo struct
  constant DB_PATH (line 22) | DB_PATH = "./foo.db"
  function checkError (line 24) | func checkError(err error) {
  function getTimeStamp (line 29) | func getTimeStamp() string {
  function insertUsingStruct (line 32) | func insertUsingStruct() int64 {
  function insertUsingMap (line 42) | func insertUsingMap() int64 {
  function getOneUserInfo (line 54) | func getOneUserInfo(id int64) Userinfo {
  function getAllUserInfo (line 61) | func getAllUserInfo(id int64) []Userinfo {
  function updateUserinfo (line 68) | func updateUserinfo(id int64) {
  function updateUsingMap (line 79) | func updateUsingMap(id int64) {
  function getMapsFromSelect (line 91) | func getMapsFromSelect(id int64) []map[string][]byte {
  function groupby (line 101) | func groupby() {
  function joinTables (line 109) | func joinTables(id int64) {
  function deleteWithUserinfo (line 117) | func deleteWithUserinfo(id int64) {
  function deleteRows (line 125) | func deleteRows() {
  function deleteAllUserinfo (line 133) | func deleteAllUserinfo(id int64) {
  function main (line 141) | func main() {

FILE: en/code/src/apps/ch.5.5/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (
  type `userdetail` (line 7) | CREATE TABLE `userdetail` (

FILE: en/code/src/apps/ch.5.6/mongodb/main.go
  type Person (line 11) | type Person struct
  function checkError (line 16) | func checkError(err error) {
  constant DB_NAME (line 23) | DB_NAME       = "test"
  constant DB_COLLECTION (line 24) | DB_COLLECTION = "people"
  function main (line 27) | func main() {

FILE: en/code/src/apps/ch.5.6/redis/main.go
  function checkError (line 10) | func checkError(err error) {
  constant DB_PORT (line 17) | DB_PORT = "9191"
  constant DB_URL (line 18) | DB_URL  = "127.0.0.1"
  function main (line 21) | func main() {

FILE: en/code/src/mymath/sqrt.go
  function Sqrt (line 6) | func Sqrt(x float64) float64 {

FILE: en/src/1.2/main.go
  function main (line 11) | func main() {

FILE: en/src/1.2/sqrt.go
  function Sqrt (line 5) | func Sqrt(x float64) float64 {

FILE: es/code/src/apps/ch.1.2/main.go
  function main (line 12) | func main() {

FILE: es/code/src/mymath/sqrt.go
  function Sqrt (line 6) | func Sqrt(x float64) float64 {

FILE: fa/code/src/apps/ch.1.2/main.go
  function main (line 12) | func main() {

FILE: fa/code/src/apps/ch.2.1/main.go
  function main (line 9) | func main() {

FILE: fa/code/src/apps/ch.2.2/main.go
  constant Pi (line 11) | Pi = 3.1415926
  constant i (line 19) | i         = 1e4
  constant MaxThread (line 20) | MaxThread = 10
  constant prefix (line 21) | prefix    = "astaxie_"
  function show_multiple_assignments (line 29) | func show_multiple_assignments() {
  function show_bool (line 49) | func show_bool() {
  function show_different_types (line 58) | func show_different_types() {
  function show_strings (line 79) | func show_strings() {
  function show_string_manipulation (line 93) | func show_string_manipulation() {
  function show_errors (line 115) | func show_errors() {
  function show_iota (line 122) | func show_iota() {
  function This_is_public (line 145) | func This_is_public()  {}
  function this_is_private (line 146) | func this_is_private() {}
  function set_default_values (line 148) | func set_default_values() {
  function show_arrays (line 164) | func show_arrays() {
  function show_slices (line 196) | func show_slices() {
  function show_map (line 237) | func show_map() {
  function main (line 265) | func main() {

FILE: fa/code/src/apps/ch.2.2/what_is_wrong_with_this/main.go
  function main (line 6) | func main() {

FILE: fa/code/src/apps/ch.2.3/basic_functions/main.go
  function max (line 8) | func max(a, b int) int {
  function main (line 15) | func main() {

FILE: fa/code/src/apps/ch.2.3/hidden_print_methods/main.go
  function f (line 7) | func f() {
  function main (line 12) | func main() {

FILE: fa/code/src/apps/ch.2.3/import_packages/main.go
  function main (line 20) | func main() {

FILE: fa/code/src/apps/ch.2.3/import_packages/only_call_init/only_call_init.go
  function init (line 5) | func init() {

FILE: fa/code/src/apps/ch.2.3/main.go
  function computedValue (line 7) | func computedValue() int {
  function show_if (line 10) | func show_if() {
  function show_if_var (line 31) | func show_if_var() {
  function show_goto (line 43) | func show_goto() {
  function show_for_loop (line 54) | func show_for_loop() {
  function show_loop_through_map (line 78) | func show_loop_through_map() {
  function show_switch (line 91) | func show_switch() {
  function show_defer (line 127) | func show_defer() {
  function main (line 134) | func main() {

FILE: fa/code/src/apps/ch.2.3/panic_and_recover/main.go
  function check_user (line 12) | func check_user() {
  function throwsPanic (line 18) | func throwsPanic(f func()) (b bool) {
  function main (line 28) | func main(){

FILE: fa/code/src/apps/ch.2.3/pass_by_value_and_pointer/main.go
  function add_by_value (line 7) | func add_by_value(a int) int {
  function add_by_reference (line 11) | func add_by_reference(a *int) int {
  function show_add_by_value (line 15) | func show_add_by_value() {
  function show_add_by_reference (line 21) | func show_add_by_reference() {
  function main (line 28) | func main() {

FILE: fa/code/src/apps/ch.2.3/type_function/main.go
  type testInt (line 7) | type testInt
  function isOdd (line 9) | func isOdd(integer int) bool {
  function isEven (line 16) | func isEven(integer int) bool {
  function filter (line 25) | func filter(slice []int, f testInt) []int {
  function init (line 34) | func init() {
  function main (line 37) | func main() {

FILE: fa/code/src/apps/ch.2.3/variadic_functions/main.go
  function SumAndProduct (line 8) | func SumAndProduct(A, B int) (int, int) {
  function main (line 12) | func main() {

FILE: fa/code/src/apps/ch.2.4/compare_age/main.go
  type person (line 8) | type person struct
  function Older (line 15) | func Older(p1, p2 person) (person, int) {
  function main (line 22) | func main() {

FILE: fa/code/src/apps/ch.2.4/embedded_structs/main.go
  type Human (line 7) | type Human struct
  type Student (line 13) | type Student struct
  function main (line 18) | func main() {

FILE: fa/code/src/apps/ch.2.4/embedded_structs2/main.go
  type Skills (line 7) | type Skills
  type Human (line 9) | type Human struct
  type Student (line 15) | type Student struct
  function main (line 22) | func main() {

FILE: fa/code/src/apps/ch.2.4/embedded_structs_with_name_conflict/main.go
  type Human (line 7) | type Human struct
  type Employee (line 13) | type Employee struct
  function main (line 19) | func main() {

FILE: fa/code/src/apps/ch.2.4/main.go
  function show_basic_struct (line 7) | func show_basic_struct() {
  function show_anonymous_struct (line 27) | func show_anonymous_struct() {
  function main (line 36) | func main() {

FILE: fa/code/src/apps/ch.2.5/attach_methods_to_struct/main.go
  type Rectangle (line 10) | type Rectangle struct
    method area (line 18) | func (r Rectangle) area() float64 {
  type Circle (line 14) | type Circle struct
    method area (line 22) | func (c Circle) area() float64 {
  function main (line 26) | func main() {

FILE: fa/code/src/apps/ch.2.5/box_example/main.go
  constant WHITE (line 6) | WHITE = iota
  constant BLACK (line 7) | BLACK
  constant BLUE (line 8) | BLUE
  constant RED (line 9) | RED
  constant YELLOW (line 10) | YELLOW
  type Color (line 13) | type Color
    method String (line 48) | func (c Color) String() string {
  type Box (line 15) | type Box struct
    method Volume (line 22) | func (b Box) Volume() float64 {
    method SetColor (line 26) | func (b *Box) SetColor(c Color) {
  type BoxList (line 20) | type BoxList
    method BiggestsColor (line 30) | func (bl BoxList) BiggestsColor() Color {
    method PaintItBlack (line 42) | func (bl BoxList) PaintItBlack() {
  function main (line 53) | func main() {

FILE: fa/code/src/apps/ch.2.5/embedded_method/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 10) | type Student struct
  type Employee (line 15) | type Employee struct
  function main (line 25) | func main() {

FILE: fa/code/src/apps/ch.2.5/method_overload/main.go
  type Human (line 5) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 11) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 25) | func (e *Employee) SayHi() {
  function main (line 30) | func main() {

FILE: fa/code/src/apps/ch.2.5/pass_struct_to_method/main.go
  type Rectangle (line 5) | type Rectangle struct
  function area (line 9) | func area(r Rectangle) float64 {
  function main (line 13) | func main() {

FILE: fa/code/src/apps/ch.2.6/interface/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 22) | func (h Human) SayHi() {
    method Sing (line 26) | func (h Human) Sing(lyrics string) {
  type Student (line 10) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 30) | func (e Employee) SayHi() {
  type Men (line 36) | type Men interface
  function main (line 41) | func main() {

FILE: fa/code/src/apps/ch.2.6/reflection/main.go
  function show_interface_none (line 8) | func show_interface_none() {
  function show_reflection (line 16) | func show_reflection() {
  function main (line 30) | func main() {

FILE: fa/code/src/apps/ch.2.6/stringer_interface/main.go
  type Human (line 8) | type Human struct
    method String (line 15) | func (h Human) String() string {
  function main (line 19) | func main() {

FILE: fa/code/src/apps/ch.2.6/switch_type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: fa/code/src/apps/ch.2.6/type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: fa/code/src/apps/ch.2.7/buffered_channel/main.go
  function main (line 7) | func main() {

FILE: fa/code/src/apps/ch.2.7/goroutine/main.go
  function say (line 10) | func say(s string) {
  function main (line 17) | func main() {

FILE: fa/code/src/apps/ch.2.7/range_and_close_channel/main.go
  function fibonacci (line 9) | func fibonacci(n int, c chan int) {
  function main (line 18) | func main() {

FILE: fa/code/src/apps/ch.2.7/select_channel/main.go
  function fibonacci (line 7) | func fibonacci(c, quit chan int) {
  function main (line 20) | func main() {

FILE: fa/code/src/apps/ch.2.7/timeout/main.go
  function main (line 11) | func main() {

FILE: fa/code/src/apps/ch.2.7/unbuffered_channel/main.go
  function sum (line 7) | func sum(a []int, c chan int) {
  function main (line 15) | func main() {

FILE: fa/code/src/apps/ch.3.2/main.go
  function sayhelloName (line 12) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 25) | func main() {

FILE: fa/code/src/apps/ch.3.4/main.go
  type MyMux (line 11) | type MyMux struct
    method ServeHTTP (line 14) | func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  function sayhelloName (line 23) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 27) | func main() {

FILE: fa/code/src/apps/ch.4.1/main.go
  function sayhelloName (line 14) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function login (line 28) | func login(w http.ResponseWriter, r *http.Request) {
  function main (line 41) | func main() {

FILE: fa/code/src/apps/ch.4.2/main.go
  constant PORT (line 15) | PORT     = "9090"
  constant HOST_URL (line 16) | HOST_URL = "http://localhost:" + PORT
  type Links (line 21) | type Links struct
  function index (line 28) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 31) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 34) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 50) | func main() {

FILE: fa/code/src/apps/ch.4.2/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: fa/code/src/apps/ch.4.3/main.go
  function index (line 13) | func index(w http.ResponseWriter, r *http.Request) {
  function templateHandler (line 23) | func templateHandler(w http.ResponseWriter, r *http.Request) {
  function main (line 35) | func main() {

FILE: fa/code/src/apps/ch.4.4/main.go
  constant PORT (line 16) | PORT     = "9090"
  constant HOST_URL (line 17) | HOST_URL = "http://localhost:" + PORT
  function index (line 23) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 26) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 29) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 45) | func main() {

FILE: fa/code/src/apps/ch.4.4/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: fa/code/src/apps/ch.4.4/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: fa/code/src/apps/ch.4.5/client_upload/main.go
  function checkError (line 13) | func checkError(err error) {
  function postFile (line 18) | func postFile(filename string, targetUrl string) {
  function main (line 42) | func main() {

FILE: fa/code/src/apps/ch.4.5/main.go
  constant MiB_UNIT (line 16) | MiB_UNIT = 1 << 20
  function checkError (line 21) | func checkError(err error) {
  function indexHandler (line 26) | func indexHandler(w http.ResponseWriter, r *http.Request) {
  function uploadHandler (line 30) | func uploadHandler(w http.ResponseWriter, r *http.Request) {
  function saveUpload (line 44) | func saveUpload(file multipart.File, handler *multipart.FileHeader) {
  function init (line 54) | func init() {
  function main (line 59) | func main() {

FILE: fa/code/src/apps/ch.4.5/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: fa/code/src/apps/ch.4.5/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: fa/code/src/apps/ch.5.2/main.go
  constant DB_USER (line 12) | DB_USER     = "user"
  constant DB_PASSWORD (line 13) | DB_PASSWORD = ""
  constant DB_NAME (line 14) | DB_NAME     = "test"
  function main (line 17) | func main() {
  function checkErr (line 72) | func checkErr(err error) {

FILE: fa/code/src/apps/ch.5.2/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: fa/code/src/apps/ch.5.3/main.go
  constant DB_PATH (line 12) | DB_PATH = "./foo.db"
  function main (line 14) | func main() {
  function checkErr (line 68) | func checkErr(err error) {

FILE: fa/code/src/apps/ch.5.3/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: fa/code/src/apps/ch.5.4/main.go
  constant DB_USER (line 14) | DB_USER     = "user"
  constant DB_PASSWORD (line 15) | DB_PASSWORD = ""
  constant DB_NAME (line 16) | DB_NAME     = "test"
  function main (line 19) | func main() {
  function checkErr (line 74) | func checkErr(err error) {

FILE: fa/code/src/apps/ch.5.4/schema.sql
  type userinfo (line 1) | CREATE TABLE userinfo

FILE: fa/code/src/apps/ch.5.5/main.go
  type Userinfo (line 15) | type Userinfo struct
  constant DB_PATH (line 22) | DB_PATH = "./foo.db"
  function checkError (line 24) | func checkError(err error) {
  function getTimeStamp (line 29) | func getTimeStamp() string {
  function insertUsingStruct (line 32) | func insertUsingStruct() int64 {
  function insertUsingMap (line 42) | func insertUsingMap() int64 {
  function getOneUserInfo (line 54) | func getOneUserInfo(id int64) Userinfo {
  function getAllUserInfo (line 61) | func getAllUserInfo(id int64) []Userinfo {
  function updateUserinfo (line 68) | func updateUserinfo(id int64) {
  function updateUsingMap (line 79) | func updateUsingMap(id int64) {
  function getMapsFromSelect (line 91) | func getMapsFromSelect(id int64) []map[string][]byte {
  function groupby (line 101) | func groupby() {
  function joinTables (line 109) | func joinTables(id int64) {
  function deleteWithUserinfo (line 117) | func deleteWithUserinfo(id int64) {
  function deleteRows (line 125) | func deleteRows() {
  function deleteAllUserinfo (line 133) | func deleteAllUserinfo(id int64) {
  function main (line 141) | func main() {

FILE: fa/code/src/apps/ch.5.5/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (
  type `userdetail` (line 7) | CREATE TABLE `userdetail` (

FILE: fa/code/src/apps/ch.5.6/mongodb/main.go
  type Person (line 11) | type Person struct
  function checkError (line 16) | func checkError(err error) {
  constant DB_NAME (line 23) | DB_NAME       = "test"
  constant DB_COLLECTION (line 24) | DB_COLLECTION = "people"
  function main (line 27) | func main() {

FILE: fa/code/src/apps/ch.5.6/redis/main.go
  function checkError (line 10) | func checkError(err error) {
  constant DB_PORT (line 17) | DB_PORT = "9191"
  constant DB_URL (line 18) | DB_URL  = "127.0.0.1"
  function main (line 21) | func main() {

FILE: fa/code/src/mymath/sqrt.go
  function Sqrt (line 6) | func Sqrt(x float64) float64 {

FILE: ja/build.go
  type Visitor (line 15) | type Visitor struct
    method md2html (line 17) | func (self *Visitor) md2html(arg map[string]string) error {
  function FixHeader (line 77) | func FixHeader(input string) string {
  function RemoveFooterLink (line 87) | func RemoveFooterLink(input string) string {
  function RemoveImageLinkSuffix (line 92) | func RemoveImageLinkSuffix(input string) string {
  function main (line 97) | func main() {

FILE: ja/src/1.2/main.go
  function main (line 11) | func main() {

FILE: ja/src/1.2/sqrt.go
  function Sqrt (line 5) | func Sqrt(x float64) float64 {

FILE: pt-br/code/src/apps/ch.1.2/main.go
  function main (line 12) | func main() {

FILE: pt-br/code/src/apps/ch.2.1/main.go
  function main (line 9) | func main() {

FILE: pt-br/code/src/apps/ch.2.2/main.go
  constant Pi (line 11) | Pi = 3.1415926
  constant i (line 19) | i         = 1e4
  constant MaxThread (line 20) | MaxThread = 10
  constant prefix (line 21) | prefix    = "astaxie_"
  function show_multiple_assignments (line 29) | func show_multiple_assignments() {
  function show_bool (line 49) | func show_bool() {
  function show_different_types (line 58) | func show_different_types() {
  function show_strings (line 79) | func show_strings() {
  function show_string_manipulation (line 93) | func show_string_manipulation() {
  function show_errors (line 115) | func show_errors() {
  function show_iota (line 122) | func show_iota() {
  function This_is_public (line 145) | func This_is_public()  {}
  function this_is_private (line 146) | func this_is_private() {}
  function set_default_values (line 148) | func set_default_values() {
  function show_arrays (line 164) | func show_arrays() {
  function show_slices (line 196) | func show_slices() {
  function show_map (line 237) | func show_map() {
  function main (line 265) | func main() {

FILE: pt-br/code/src/apps/ch.2.2/what_is_wrong_with_this/main.go
  function main (line 6) | func main() {

FILE: pt-br/code/src/apps/ch.2.3/basic_functions/main.go
  function max (line 8) | func max(a, b int) int {
  function main (line 15) | func main() {

FILE: pt-br/code/src/apps/ch.2.3/hidden_print_methods/main.go
  function f (line 7) | func f() {
  function main (line 12) | func main() {

FILE: pt-br/code/src/apps/ch.2.3/import_packages/main.go
  function main (line 19) | func main() {

FILE: pt-br/code/src/apps/ch.2.3/import_packages/only_call_init/only_call_init.go
  function init (line 5) | func init() {

FILE: pt-br/code/src/apps/ch.2.3/main.go
  function computedValue (line 7) | func computedValue() int {
  function show_if (line 10) | func show_if() {
  function show_if_var (line 31) | func show_if_var() {
  function show_goto (line 43) | func show_goto() {
  function show_for_loop (line 54) | func show_for_loop() {
  function show_loop_through_map (line 78) | func show_loop_through_map() {
  function show_switch (line 91) | func show_switch() {
  function show_defer (line 127) | func show_defer() {
  function main (line 134) | func main() {

FILE: pt-br/code/src/apps/ch.2.3/panic_and_recover/main.go
  function check_user (line 12) | func check_user() {
  function throwsPanic (line 18) | func throwsPanic(f func()) (b bool) {
  function main (line 28) | func main(){

FILE: pt-br/code/src/apps/ch.2.3/pass_by_value_and_pointer/main.go
  function add_by_value (line 7) | func add_by_value(a int) int {
  function add_by_reference (line 11) | func add_by_reference(a *int) int {
  function show_add_by_value (line 15) | func show_add_by_value() {
  function show_add_by_reference (line 21) | func show_add_by_reference() {
  function main (line 28) | func main() {

FILE: pt-br/code/src/apps/ch.2.3/type_function/main.go
  type testInt (line 7) | type testInt
  function isOdd (line 9) | func isOdd(integer int) bool {
  function isEven (line 16) | func isEven(integer int) bool {
  function filter (line 25) | func filter(slice []int, f testInt) []int {
  function init (line 34) | func init() {
  function main (line 37) | func main() {

FILE: pt-br/code/src/apps/ch.2.3/variadic_functions/main.go
  function SumAndProduct (line 8) | func SumAndProduct(A, B int) (int, int) {
  function main (line 12) | func main() {

FILE: pt-br/code/src/apps/ch.2.4/compare_age/main.go
  type person (line 8) | type person struct
  function Older (line 15) | func Older(p1, p2 person) (person, int) {
  function main (line 22) | func main() {

FILE: pt-br/code/src/apps/ch.2.4/embedded_structs/main.go
  type Human (line 7) | type Human struct
  type Student (line 13) | type Student struct
  function main (line 18) | func main() {

FILE: pt-br/code/src/apps/ch.2.4/embedded_structs2/main.go
  type Skills (line 7) | type Skills
  type Human (line 9) | type Human struct
  type Student (line 15) | type Student struct
  function main (line 22) | func main() {

FILE: pt-br/code/src/apps/ch.2.4/embedded_structs_with_name_conflict/main.go
  type Human (line 7) | type Human struct
  type Employee (line 13) | type Employee struct
  function main (line 19) | func main() {

FILE: pt-br/code/src/apps/ch.2.4/main.go
  function show_basic_struct (line 7) | func show_basic_struct() {
  function show_anonymous_struct (line 27) | func show_anonymous_struct() {
  function main (line 36) | func main() {

FILE: pt-br/code/src/apps/ch.2.5/attach_methods_to_struct/main.go
  type Rectangle (line 10) | type Rectangle struct
    method area (line 18) | func (r Rectangle) area() float64 {
  type Circle (line 14) | type Circle struct
    method area (line 22) | func (c Circle) area() float64 {
  function main (line 26) | func main() {

FILE: pt-br/code/src/apps/ch.2.5/box_example/main.go
  constant WHITE (line 6) | WHITE = iota
  constant BLACK (line 7) | BLACK
  constant BLUE (line 8) | BLUE
  constant RED (line 9) | RED
  constant YELLOW (line 10) | YELLOW
  type Color (line 13) | type Color
    method String (line 48) | func (c Color) String() string {
  type Box (line 15) | type Box struct
    method Volume (line 22) | func (b Box) Volume() float64 {
    method SetColor (line 26) | func (b *Box) SetColor(c Color) {
  type BoxList (line 20) | type BoxList
    method BiggestsColor (line 30) | func (bl BoxList) BiggestsColor() Color {
    method PaintItBlack (line 42) | func (bl BoxList) PaintItBlack() {
  function main (line 53) | func main() {

FILE: pt-br/code/src/apps/ch.2.5/embedded_method/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 10) | type Student struct
  type Employee (line 15) | type Employee struct
  function main (line 25) | func main() {

FILE: pt-br/code/src/apps/ch.2.5/method_overload/main.go
  type Human (line 5) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 11) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 25) | func (e *Employee) SayHi() {
  function main (line 30) | func main() {

FILE: pt-br/code/src/apps/ch.2.5/pass_struct_to_method/main.go
  type Rectangle (line 5) | type Rectangle struct
  function area (line 9) | func area(r Rectangle) float64 {
  function main (line 13) | func main() {

FILE: pt-br/code/src/apps/ch.2.6/interface/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 22) | func (h Human) SayHi() {
    method Sing (line 26) | func (h Human) Sing(lyrics string) {
  type Student (line 10) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 30) | func (e Employee) SayHi() {
  type Men (line 36) | type Men interface
  function main (line 41) | func main() {

FILE: pt-br/code/src/apps/ch.2.6/reflection/main.go
  function show_interface_none (line 8) | func show_interface_none() {
  function show_reflection (line 16) | func show_reflection() {
  function main (line 30) | func main() {

FILE: pt-br/code/src/apps/ch.2.6/stringer_interface/main.go
  type Human (line 8) | type Human struct
    method String (line 15) | func (h Human) String() string {
  function main (line 19) | func main() {

FILE: pt-br/code/src/apps/ch.2.6/switch_type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: pt-br/code/src/apps/ch.2.6/type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: pt-br/code/src/apps/ch.2.7/buffered_channel/main.go
  function main (line 7) | func main() {

FILE: pt-br/code/src/apps/ch.2.7/goroutine/main.go
  function say (line 10) | func say(s string) {
  function main (line 17) | func main() {

FILE: pt-br/code/src/apps/ch.2.7/range_and_close_channel/main.go
  function fibonacci (line 9) | func fibonacci(n int, c chan int) {
  function main (line 18) | func main() {

FILE: pt-br/code/src/apps/ch.2.7/select_channel/main.go
  function fibonacci (line 7) | func fibonacci(c, quit chan int) {
  function main (line 20) | func main() {

FILE: pt-br/code/src/apps/ch.2.7/timeout/main.go
  function main (line 11) | func main() {

FILE: pt-br/code/src/apps/ch.2.7/unbuffered_channel/main.go
  function sum (line 7) | func sum(a []int, c chan int) {
  function main (line 15) | func main() {

FILE: pt-br/code/src/apps/ch.3.2/main.go
  function sayhelloName (line 12) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 25) | func main() {

FILE: pt-br/code/src/apps/ch.3.4/main.go
  type MyMux (line 11) | type MyMux struct
    method ServeHTTP (line 14) | func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  function sayhelloName (line 23) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 27) | func main() {

FILE: pt-br/code/src/apps/ch.4.1/main.go
  function sayhelloName (line 14) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function login (line 28) | func login(w http.ResponseWriter, r *http.Request) {
  function main (line 41) | func main() {

FILE: pt-br/code/src/apps/ch.4.2/main.go
  constant PORT (line 15) | PORT     = "9090"
  constant HOST_URL (line 16) | HOST_URL = "http://localhost:" + PORT
  type Links (line 21) | type Links struct
  function index (line 28) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 31) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 34) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 50) | func main() {

FILE: pt-br/code/src/apps/ch.4.2/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: pt-br/code/src/apps/ch.4.3/main.go
  function index (line 13) | func index(w http.ResponseWriter, r *http.Request) {
  function templateHandler (line 23) | func templateHandler(w http.ResponseWriter, r *http.Request) {
  function main (line 35) | func main() {

FILE: pt-br/code/src/apps/ch.4.4/main.go
  constant PORT (line 16) | PORT     = "9090"
  constant HOST_URL (line 17) | HOST_URL = "http://localhost:" + PORT
  function index (line 23) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 26) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 29) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 45) | func main() {

FILE: pt-br/code/src/apps/ch.4.4/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: pt-br/code/src/apps/ch.4.4/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: pt-br/code/src/apps/ch.4.5/client_upload/main.go
  function checkError (line 13) | func checkError(err error) {
  function postFile (line 18) | func postFile(filename string, targetUrl string) {
  function main (line 42) | func main() {

FILE: pt-br/code/src/apps/ch.4.5/main.go
  constant MiB_UNIT (line 16) | MiB_UNIT = 1 << 20
  function checkError (line 21) | func checkError(err error) {
  function indexHandler (line 26) | func indexHandler(w http.ResponseWriter, r *http.Request) {
  function uploadHandler (line 30) | func uploadHandler(w http.ResponseWriter, r *http.Request) {
  function saveUpload (line 44) | func saveUpload(file multipart.File, handler *multipart.FileHeader) {
  function init (line 54) | func init() {
  function main (line 59) | func main() {

FILE: pt-br/code/src/apps/ch.4.5/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: pt-br/code/src/apps/ch.4.5/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: pt-br/code/src/apps/ch.5.2/main.go
  constant DB_USER (line 12) | DB_USER     = "user"
  constant DB_PASSWORD (line 13) | DB_PASSWORD = ""
  constant DB_NAME (line 14) | DB_NAME     = "test"
  function main (line 17) | func main() {
  function checkErr (line 72) | func checkErr(err error) {

FILE: pt-br/code/src/apps/ch.5.2/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: pt-br/code/src/apps/ch.5.3/main.go
  constant DB_PATH (line 12) | DB_PATH = "./foo.db"
  function main (line 14) | func main() {
  function checkErr (line 68) | func checkErr(err error) {

FILE: pt-br/code/src/apps/ch.5.3/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: pt-br/code/src/apps/ch.5.4/main.go
  constant DB_USER (line 14) | DB_USER     = "user"
  constant DB_PASSWORD (line 15) | DB_PASSWORD = ""
  constant DB_NAME (line 16) | DB_NAME     = "test"
  function main (line 19) | func main() {
  function checkErr (line 74) | func checkErr(err error) {

FILE: pt-br/code/src/apps/ch.5.4/schema.sql
  type userinfo (line 1) | CREATE TABLE userinfo

FILE: pt-br/code/src/apps/ch.5.5/main.go
  type Userinfo (line 15) | type Userinfo struct
  constant DB_PATH (line 22) | DB_PATH = "./foo.db"
  function checkError (line 24) | func checkError(err error) {
  function getTimeStamp (line 29) | func getTimeStamp() string {
  function insertUsingStruct (line 32) | func insertUsingStruct() int64 {
  function insertUsingMap (line 42) | func insertUsingMap() int64 {
  function getOneUserInfo (line 54) | func getOneUserInfo(id int64) Userinfo {
  function getAllUserInfo (line 61) | func getAllUserInfo(id int64) []Userinfo {
  function updateUserinfo (line 68) | func updateUserinfo(id int64) {
  function updateUsingMap (line 79) | func updateUsingMap(id int64) {
  function getMapsFromSelect (line 91) | func getMapsFromSelect(id int64) []map[string][]byte {
  function groupby (line 101) | func groupby() {
  function joinTables (line 109) | func joinTables(id int64) {
  function deleteWithUserinfo (line 117) | func deleteWithUserinfo(id int64) {
  function deleteRows (line 125) | func deleteRows() {
  function deleteAllUserinfo (line 133) | func deleteAllUserinfo(id int64) {
  function main (line 141) | func main() {

FILE: pt-br/code/src/apps/ch.5.5/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (
  type `userdetail` (line 7) | CREATE TABLE `userdetail` (

FILE: pt-br/code/src/apps/ch.5.6/mongodb/main.go
  type Person (line 11) | type Person struct
  function checkError (line 16) | func checkError(err error) {
  constant DB_NAME (line 23) | DB_NAME       = "test"
  constant DB_COLLECTION (line 24) | DB_COLLECTION = "people"
  function main (line 27) | func main() {

FILE: pt-br/code/src/apps/ch.5.6/redis/main.go
  function checkError (line 10) | func checkError(err error) {
  constant DB_PORT (line 17) | DB_PORT = "9191"
  constant DB_URL (line 18) | DB_URL  = "127.0.0.1"
  function main (line 21) | func main() {

FILE: pt-br/code/src/mymath/sqrt.go
  function Sqrt (line 6) | func Sqrt(x float64) float64 {

FILE: th/build.go
  type Visitor (line 15) | type Visitor struct
    method md2html (line 17) | func (self *Visitor) md2html(arg map[string]string) error {
  function FixHeader (line 77) | func FixHeader(input string) string {
  function RemoveFooterLink (line 87) | func RemoveFooterLink(input string) string {
  function RemoveImageLinkSuffix (line 92) | func RemoveImageLinkSuffix(input string) string {
  function main (line 97) | func main() {

FILE: th/code/src/apps/ch.1.2/main.go
  function main (line 12) | func main() {

FILE: th/code/src/apps/ch.2.1/main.go
  function main (line 9) | func main() {

FILE: th/code/src/apps/ch.2.2/main.go
  constant Pi (line 11) | Pi = 3.1415926
  constant i (line 19) | i         = 1e4
  constant MaxThread (line 20) | MaxThread = 10
  constant prefix (line 21) | prefix    = "astaxie_"
  function show_multiple_assignments (line 29) | func show_multiple_assignments() {
  function show_bool (line 49) | func show_bool() {
  function show_different_types (line 58) | func show_different_types() {
  function show_strings (line 79) | func show_strings() {
  function show_string_manipulation (line 93) | func show_string_manipulation() {
  function show_errors (line 115) | func show_errors() {
  function show_iota (line 122) | func show_iota() {
  function This_is_public (line 145) | func This_is_public()  {}
  function this_is_private (line 146) | func this_is_private() {}
  function set_default_values (line 148) | func set_default_values() {
  function show_arrays (line 164) | func show_arrays() {
  function show_slices (line 196) | func show_slices() {
  function show_map (line 237) | func show_map() {
  function main (line 265) | func main() {

FILE: th/code/src/apps/ch.2.2/what_is_wrong_with_this/main.go
  function main (line 6) | func main() {

FILE: th/code/src/apps/ch.2.3/basic_functions/main.go
  function max (line 8) | func max(a, b int) int {
  function main (line 15) | func main() {

FILE: th/code/src/apps/ch.2.3/hidden_print_methods/main.go
  function f (line 7) | func f() {
  function main (line 12) | func main() {

FILE: th/code/src/apps/ch.2.3/import_packages/main.go
  function main (line 20) | func main() {

FILE: th/code/src/apps/ch.2.3/import_packages/only_call_init/only_call_init.go
  function init (line 5) | func init() {

FILE: th/code/src/apps/ch.2.3/main.go
  function computedValue (line 7) | func computedValue() int {
  function show_if (line 10) | func show_if() {
  function show_if_var (line 31) | func show_if_var() {
  function show_goto (line 43) | func show_goto() {
  function show_for_loop (line 54) | func show_for_loop() {
  function show_loop_through_map (line 78) | func show_loop_through_map() {
  function show_switch (line 91) | func show_switch() {
  function show_defer (line 127) | func show_defer() {
  function main (line 134) | func main() {

FILE: th/code/src/apps/ch.2.3/panic_and_recover/main.go
  function check_user (line 12) | func check_user() {
  function throwsPanic (line 18) | func throwsPanic(f func()) (b bool) {
  function main (line 28) | func main(){

FILE: th/code/src/apps/ch.2.3/pass_by_value_and_pointer/main.go
  function add_by_value (line 7) | func add_by_value(a int) int {
  function add_by_reference (line 11) | func add_by_reference(a *int) int {
  function show_add_by_value (line 15) | func show_add_by_value() {
  function show_add_by_reference (line 21) | func show_add_by_reference() {
  function main (line 28) | func main() {

FILE: th/code/src/apps/ch.2.3/type_function/main.go
  type testInt (line 7) | type testInt
  function isOdd (line 9) | func isOdd(integer int) bool {
  function isEven (line 16) | func isEven(integer int) bool {
  function filter (line 25) | func filter(slice []int, f testInt) []int {
  function init (line 34) | func init() {
  function main (line 37) | func main() {

FILE: th/code/src/apps/ch.2.3/variadic_functions/main.go
  function SumAndProduct (line 8) | func SumAndProduct(A, B int) (int, int) {
  function main (line 12) | func main() {

FILE: th/code/src/apps/ch.2.4/compare_age/main.go
  type person (line 8) | type person struct
  function Older (line 15) | func Older(p1, p2 person) (person, int) {
  function main (line 22) | func main() {

FILE: th/code/src/apps/ch.2.4/embedded_structs/main.go
  type Human (line 7) | type Human struct
  type Student (line 13) | type Student struct
  function main (line 18) | func main() {

FILE: th/code/src/apps/ch.2.4/embedded_structs2/main.go
  type Skills (line 7) | type Skills
  type Human (line 9) | type Human struct
  type Student (line 15) | type Student struct
  function main (line 22) | func main() {

FILE: th/code/src/apps/ch.2.4/embedded_structs_with_name_conflict/main.go
  type Human (line 7) | type Human struct
  type Employee (line 13) | type Employee struct
  function main (line 19) | func main() {

FILE: th/code/src/apps/ch.2.4/main.go
  function show_basic_struct (line 7) | func show_basic_struct() {
  function show_anonymous_struct (line 27) | func show_anonymous_struct() {
  function main (line 36) | func main() {

FILE: th/code/src/apps/ch.2.5/attach_methods_to_struct/main.go
  type Rectangle (line 10) | type Rectangle struct
    method area (line 18) | func (r Rectangle) area() float64 {
  type Circle (line 14) | type Circle struct
    method area (line 22) | func (c Circle) area() float64 {
  function main (line 26) | func main() {

FILE: th/code/src/apps/ch.2.5/box_example/main.go
  constant WHITE (line 6) | WHITE = iota
  constant BLACK (line 7) | BLACK
  constant BLUE (line 8) | BLUE
  constant RED (line 9) | RED
  constant YELLOW (line 10) | YELLOW
  type Color (line 13) | type Color
    method String (line 48) | func (c Color) String() string {
  type Box (line 15) | type Box struct
    method Volume (line 22) | func (b Box) Volume() float64 {
    method SetColor (line 26) | func (b *Box) SetColor(c Color) {
  type BoxList (line 20) | type BoxList
    method BiggestsColor (line 30) | func (bl BoxList) BiggestsColor() Color {
    method PaintItBlack (line 42) | func (bl BoxList) PaintItBlack() {
  function main (line 53) | func main() {

FILE: th/code/src/apps/ch.2.5/embedded_method/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 10) | type Student struct
  type Employee (line 15) | type Employee struct
  function main (line 25) | func main() {

FILE: th/code/src/apps/ch.2.5/method_overload/main.go
  type Human (line 5) | type Human struct
    method SayHi (line 21) | func (h *Human) SayHi() {
  type Student (line 11) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 25) | func (e *Employee) SayHi() {
  function main (line 30) | func main() {

FILE: th/code/src/apps/ch.2.5/pass_struct_to_method/main.go
  type Rectangle (line 5) | type Rectangle struct
  function area (line 9) | func area(r Rectangle) float64 {
  function main (line 13) | func main() {

FILE: th/code/src/apps/ch.2.6/interface/main.go
  type Human (line 4) | type Human struct
    method SayHi (line 22) | func (h Human) SayHi() {
    method Sing (line 26) | func (h Human) Sing(lyrics string) {
  type Student (line 10) | type Student struct
  type Employee (line 16) | type Employee struct
    method SayHi (line 30) | func (e Employee) SayHi() {
  type Men (line 36) | type Men interface
  function main (line 41) | func main() {

FILE: th/code/src/apps/ch.2.6/reflection/main.go
  function show_interface_none (line 8) | func show_interface_none() {
  function show_reflection (line 16) | func show_reflection() {
  function main (line 30) | func main() {

FILE: th/code/src/apps/ch.2.6/stringer_interface/main.go
  type Human (line 8) | type Human struct
    method String (line 15) | func (h Human) String() string {
  function main (line 19) | func main() {

FILE: th/code/src/apps/ch.2.6/switch_type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: th/code/src/apps/ch.2.6/type_check/main.go
  type Element (line 8) | type Element interface
  type List (line 9) | type List
  type Person (line 11) | type Person struct
    method String (line 16) | func (p Person) String() string {
  function main (line 20) | func main() {

FILE: th/code/src/apps/ch.2.7/buffered_channel/main.go
  function main (line 7) | func main() {

FILE: th/code/src/apps/ch.2.7/goroutine/main.go
  function say (line 10) | func say(s string) {
  function main (line 17) | func main() {

FILE: th/code/src/apps/ch.2.7/range_and_close_channel/main.go
  function fibonacci (line 9) | func fibonacci(n int, c chan int) {
  function main (line 18) | func main() {

FILE: th/code/src/apps/ch.2.7/select_channel/main.go
  function fibonacci (line 7) | func fibonacci(c, quit chan int) {
  function main (line 20) | func main() {

FILE: th/code/src/apps/ch.2.7/timeout/main.go
  function main (line 11) | func main() {

FILE: th/code/src/apps/ch.2.7/unbuffered_channel/main.go
  function sum (line 7) | func sum(a []int, c chan int) {
  function main (line 15) | func main() {

FILE: th/code/src/apps/ch.3.2/main.go
  function sayhelloName (line 12) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 25) | func main() {

FILE: th/code/src/apps/ch.3.4/main.go
  type MyMux (line 11) | type MyMux struct
    method ServeHTTP (line 14) | func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  function sayhelloName (line 23) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function main (line 27) | func main() {

FILE: th/code/src/apps/ch.4.1/main.go
  function sayhelloName (line 14) | func sayhelloName(w http.ResponseWriter, r *http.Request) {
  function login (line 28) | func login(w http.ResponseWriter, r *http.Request) {
  function main (line 41) | func main() {

FILE: th/code/src/apps/ch.4.2/main.go
  constant PORT (line 15) | PORT     = "9090"
  constant HOST_URL (line 16) | HOST_URL = "http://localhost:" + PORT
  type Links (line 21) | type Links struct
  function index (line 28) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 31) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 34) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 50) | func main() {

FILE: th/code/src/apps/ch.4.2/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: th/code/src/apps/ch.4.3/main.go
  function index (line 13) | func index(w http.ResponseWriter, r *http.Request) {
  function templateHandler (line 23) | func templateHandler(w http.ResponseWriter, r *http.Request) {
  function main (line 35) | func main() {

FILE: th/code/src/apps/ch.4.4/main.go
  constant PORT (line 16) | PORT     = "9090"
  constant HOST_URL (line 17) | HOST_URL = "http://localhost:" + PORT
  function index (line 23) | func index(w http.ResponseWriter, r *http.Request) {
  function profileHandler (line 26) | func profileHandler(w http.ResponseWriter, r *http.Request) {
  function checkProfile (line 29) | func checkProfile(w http.ResponseWriter, r *http.Request) {
  function init (line 41) | func init() {
  function main (line 45) | func main() {

FILE: th/code/src/apps/ch.4.4/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: th/code/src/apps/ch.4.4/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: th/code/src/apps/ch.4.5/client_upload/main.go
  function checkError (line 13) | func checkError(err error) {
  function postFile (line 18) | func postFile(filename string, targetUrl string) {
  function main (line 42) | func main() {

FILE: th/code/src/apps/ch.4.5/main.go
  constant MiB_UNIT (line 16) | MiB_UNIT = 1 << 20
  function checkError (line 21) | func checkError(err error) {
  function indexHandler (line 26) | func indexHandler(w http.ResponseWriter, r *http.Request) {
  function uploadHandler (line 30) | func uploadHandler(w http.ResponseWriter, r *http.Request) {
  function saveUpload (line 44) | func saveUpload(file multipart.File, handler *multipart.FileHeader) {
  function init (line 54) | func init() {
  function main (line 59) | func main() {

FILE: th/code/src/apps/ch.4.5/nonce/main.go
  type Nonce (line 16) | type Nonce struct
  type Nonces (line 21) | type Nonces struct
    method NewNonce (line 28) | func (n *Nonces) NewNonce() Nonce {
    method NewToken (line 33) | func (n *Nonces) NewToken() string {
    method HasToken (line 42) | func (n *Nonces) HasToken(token string) bool {
    method MarkToken (line 45) | func (n *Nonces) MarkToken(token string) {
    method CheckToken (line 48) | func (n *Nonces) CheckToken(token string) error {
    method CheckThenMarkToken (line 57) | func (n *Nonces) CheckThenMarkToken(token string) error {
  function New (line 25) | func New() Nonces {
  function createToken (line 64) | func createToken() string {

FILE: th/code/src/apps/ch.4.5/validator/main.go
  type ProfilePage (line 14) | type ProfilePage struct
    method GetErrors (line 23) | func (p *ProfilePage) GetErrors() Errors {
  type Errors (line 17) | type Errors struct
  constant mmddyyyyForm (line 46) | mmddyyyyForm = "01/02/2006"
  constant yyyymmddForm (line 47) | yyyymmddForm = "2006-01-02"
  function doSlicesIntersect (line 66) | func doSlicesIntersect(s1, s2 []string) bool {
  function isElementInSlice (line 77) | func isElementInSlice(str string, sl []string) bool {
  function checkChineseName (line 90) | func checkChineseName(str string) error {
  function checkUsername (line 100) | func checkUsername(str string) error {
  function checkAge (line 108) | func checkAge(str string) error {
  function checkEmail (line 121) | func checkEmail(str string) error {
  function checkDate (line 130) | func checkDate(str string) error {
  function checkGender (line 142) | func checkGender(str string) error {
  function checkSibling (line 154) | func checkSibling(strs []string) error {
  function checkShirtSize (line 166) | func checkShirtSize(str string) error {

FILE: th/code/src/apps/ch.5.2/main.go
  constant DB_USER (line 12) | DB_USER     = "user"
  constant DB_PASSWORD (line 13) | DB_PASSWORD = ""
  constant DB_NAME (line 14) | DB_NAME     = "test"
  function main (line 17) | func main() {
  function checkErr (line 72) | func checkErr(err error) {

FILE: th/code/src/apps/ch.5.2/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: th/code/src/apps/ch.5.3/main.go
  constant DB_PATH (line 12) | DB_PATH = "./foo.db"
  function main (line 14) | func main() {
  function checkErr (line 68) | func checkErr(err error) {

FILE: th/code/src/apps/ch.5.3/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (

FILE: th/code/src/apps/ch.5.4/main.go
  constant DB_USER (line 14) | DB_USER     = "user"
  constant DB_PASSWORD (line 15) | DB_PASSWORD = ""
  constant DB_NAME (line 16) | DB_NAME     = "test"
  function main (line 19) | func main() {
  function checkErr (line 74) | func checkErr(err error) {

FILE: th/code/src/apps/ch.5.4/schema.sql
  type userinfo (line 1) | CREATE TABLE userinfo

FILE: th/code/src/apps/ch.5.5/main.go
  type Userinfo (line 15) | type Userinfo struct
  constant DB_PATH (line 22) | DB_PATH = "./foo.db"
  function checkError (line 24) | func checkError(err error) {
  function getTimeStamp (line 29) | func getTimeStamp() string {
  function insertUsingStruct (line 32) | func insertUsingStruct() int64 {
  function insertUsingMap (line 42) | func insertUsingMap() int64 {
  function getOneUserInfo (line 54) | func getOneUserInfo(id int64) Userinfo {
  function getAllUserInfo (line 61) | func getAllUserInfo(id int64) []Userinfo {
  function updateUserinfo (line 68) | func updateUserinfo(id int64) {
  function updateUsingMap (line 79) | func updateUsingMap(id int64) {
  function getMapsFromSelect (line 91) | func getMapsFromSelect(id int64) []map[string][]byte {
  function groupby (line 101) | func groupby() {
  function joinTables (line 109) | func joinTables(id int64) {
  function deleteWithUserinfo (line 117) | func deleteWithUserinfo(id int64) {
  function deleteRows (line 125) | func deleteRows() {
  function deleteAllUserinfo (line 133) | func deleteAllUserinfo(id int64) {
  function main (line 141) | func main() {

FILE: th/code/src/apps/ch.5.5/schema.sql
  type `userinfo` (line 1) | CREATE TABLE `userinfo` (
  type `userdetail` (line 7) | CREATE TABLE `userdetail` (

FILE: th/code/src/apps/ch.5.6/mongodb/main.go
  type Person (line 11) | type Person struct
  function checkError (line 16) | func checkError(err error) {
  constant DB_NAME (line 23) | DB_NAME       = "test"
  constant DB_COLLECTION (line 24) | DB_COLLECTION = "people"
  function main (line 27) | func main() {

FILE: th/code/src/apps/ch.5.6/redis/main.go
  function checkError (line 10) | func checkError(err error) {
  constant DB_PORT (line 17) | DB_PORT = "9191"
  constant DB_URL (line 18) | DB_URL  = "127.0.0.1"
  function main (line 21) | func main() {

FILE: th/code/src/mymath/sqrt.go
  function Sqrt (line 6) | func Sqrt(x float64) float64 {

FILE: th/src/1.2/main.go
  function main (line 11) | func main() {

FILE: th/src/1.2/sqrt.go
  function Sqrt (line 5) | func Sqrt(x float64) float64 {

FILE: zh-tw/a_herf.go
  function dir (line 10) | func dir()([]string,error) {
  function htmlfile (line 36) | func  htmlfile(filename string,next_path string,last_path string)(error){
  function nextandlast (line 62) | func nextandlast(filenames []string,index int )(filename string,next_pat...
  function main (line 81) | func main(){

FILE: zh-tw/build.go
  type Visitor (line 15) | type Visitor struct
    method md2html (line 17) | func (self *Visitor) md2html(arg map[string]string) error {
  function FixHeader (line 86) | func FixHeader(input string) string {
  function RemoveFooterLink (line 96) | func RemoveFooterLink(input string) string {
  function RemoveImageLinkSuffix (line 101) | func RemoveImageLinkSuffix(input string) string {
  function main (line 106) | func main() {

FILE: zh-tw/build_new.go
  constant token (line 15) | token = ""
  type Visitor (line 18) | type Visitor struct
    method md2html (line 20) | func (self *Visitor) md2html(arg map[string]string) error {
  function FixHeader (line 109) | func FixHeader(input string) string {
  function RemoveFooterLink (line 119) | func RemoveFooterLink(input string) string {
  function RemoveImageLinkSuffix (line 124) | func RemoveImageLinkSuffix(input string) string {
  function main (line 129) | func main() {

FILE: zh-tw/src/1.2/main.go
  function main (line 11) | func main() {

FILE: zh-tw/src/1.2/sqrt.go
  function Sqrt (line 5) | func Sqrt(x float64) float64 {

FILE: zh/a_herf.go
  function dir (line 10) | func dir()([]string,error) {
  function htmlfile (line 36) | func  htmlfile(filename string,next_path string,last_path string)(error){
  function nextandlast (line 62) | func nextandlast(filenames []string,index int )(filename string,next_pat...
  function main (line 81) | func main(){

FILE: zh/build.go
  type Visitor (line 15) | type Visitor struct
    method md2html (line 17) | func (self *Visitor) md2html(arg map[string]string) error {
  function FixHeader (line 86) | func FixHeader(input string) string {
  function RemoveFooterLink (line 96) | func RemoveFooterLink(input string) string {
  function RemoveImageLinkSuffix (line 101) | func RemoveImageLinkSuffix(input string) string {
  function main (line 106) | func main() {

FILE: zh/build_new.go
  constant token (line 15) | token = ""
  type Visitor (line 18) | type Visitor struct
    method md2html (line 20) | func (self *Visitor) md2html(arg map[string]string) error {
  function FixHeader (line 109) | func FixHeader(input string) string {
  function RemoveFooterLink (line 119) | func RemoveFooterLink(input string) string {
  function RemoveImageLinkSuffix (line 124) | func RemoveImageLinkSuffix(input string) string {
  function main (line 129) | func main() {
Condensed preview — 1809 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,921K chars).
[
  {
    "path": "LANGS.md",
    "chars": 188,
    "preview": "* [Deutsch](de/)\n* [English](en/)\n* [Español](es/)\n* [Français](fr/)\n* [Português - Brasil](pt-br/)\n* [Русский](ru/)\n* ["
  },
  {
    "path": "LICENSE.md",
    "chars": 1493,
    "preview": "Copyright (c) 2012, AstaXie and The Contributors\nAll rights reserved.\n\nRedistribution and use in source and binary forms"
  },
  {
    "path": "README.md",
    "chars": 1526,
    "preview": "# Multiple Language Versions\r\n\r\n* [(HTML - PDF) on GitBook](https://astaxie.gitbooks.io/build-web-application-with-golan"
  },
  {
    "path": "bn/01.0.md",
    "chars": 1163,
    "preview": "# ১ গো এনভায়রনমেন্ট কনফিগারেশন\n\nগো এর ভুবনে আপনাকে স্বাগতম! পরম করুণাময় সৃষ্টিকর্তার নামে শুরু করছি।\n\nগো একটি ওপেনসোর্স,"
  },
  {
    "path": "bn/01.1.md",
    "chars": 7567,
    "preview": "# ইনস্টলেশন ১.১\n\n## ইনস্টলেশন ১.১\nআপনার কম্পিউটারে গো এর পরিবেশ কনফিগার করার অনেক উপায় আছে এবং আপনি আপনার পছন্দ মত যে ক"
  },
  {
    "path": "bn/preface.md",
    "chars": 3239,
    "preview": "- ১.[গো এনভায়রনমেন্ট কনফিগারেশন](01.0.md)\n\t- ১.১. [ইনস্টলেশন](01.1.md)\n\t- ১.২. [গো-পাথ এবং ওয়ার্কস্পেস](01.2.md)\n\t- ১.৩."
  },
  {
    "path": "bn/ref.md",
    "chars": 732,
    "preview": "# Appendix A References\n\nThis book is a summary of my Go experience, some content are from other Gophers' either blogs o"
  },
  {
    "path": "de/01.0.md",
    "chars": 1916,
    "preview": "# 1 Einrichtung der Go Entwicklungsumgebung\n\nWillkommen in der Welt von Go. Lass sie uns erforschen.\n\nGo ist eine schnel"
  },
  {
    "path": "de/01.1.md",
    "chars": 7449,
    "preview": "# 1.1 Installation\n\n## Drei Wege Go zu installieren\n\nEs gibt viele Wege, um eine Go-Entwicklungsumgebung auf Deinem Comp"
  },
  {
    "path": "de/01.2.md",
    "chars": 6209,
    "preview": "# 1.2 $GOPATH und Workspaces\n\n## $GOPATH\n\nAlle Go-Befehle bauen auf einer wichtigen Umgebungsvariable mit dem Namen $GOP"
  },
  {
    "path": "de/01.3.md",
    "chars": 7663,
    "preview": "# 1.3 Go Befehle\n\n## Go Befehle\n\nDie Programmiersprache Go bringt viele nützliche Befehle für diverse Anwendungszwecke m"
  },
  {
    "path": "de/01.4.md",
    "chars": 15770,
    "preview": "# Go Entwicklungswerkzeuge\n\nIn diesem Abschnitt werde ich Dir ein paar IDEs (***Integrated Developement Environments***)"
  },
  {
    "path": "de/01.5.md",
    "chars": 972,
    "preview": "# 1.5 Zusammenfassung\n\nIn diesem Kapitel haben wir die Installation auf drei verschiedene Arten besprochen. Dies waren d"
  },
  {
    "path": "de/02.0.md",
    "chars": 1109,
    "preview": "# 2 Grundlegendes Wissen zu Go\n\nGo ist eine kompilierte, systemnahe Programmiersprache und ist verwandt mit der C-Famili"
  },
  {
    "path": "de/02.1.md",
    "chars": 3447,
    "preview": "# 2.1 Hallo Go\n\nBevor wir unsere erste Anwendung in Go erstellen, müssen wir erst klein anfangen. Du kannst nicht erwart"
  },
  {
    "path": "de/02.2.md",
    "chars": 21415,
    "preview": "# 2.2 Grundlagen von Go\n\nIn diesem Abschnit werden wir lernen, wie man Konstanten und Variablen mit grundlegenden Datent"
  },
  {
    "path": "de/02.3.md",
    "chars": 21187,
    "preview": "# 2.3 Kontrollstrukturen und Funktionen\n\nIn diesem Kapite\nwerfen wir einen Blick auf Kontrollstrukturen und Funktionen i"
  },
  {
    "path": "de/02.4.md",
    "chars": 7928,
    "preview": "# 2.4 Struct\n\n## Struct\n\nWie in anderen Programmiersprachen können wir auch in Go neue Datentypen erstellen, die als ein"
  },
  {
    "path": "de/02.5.md",
    "chars": 10987,
    "preview": "# 2.5 Objektorientierte Programmierung\n\nIn den letzen beiden Abschnitten hatten wir uns mit Funktionen und Structs besch"
  },
  {
    "path": "de/02.6.md",
    "chars": 13977,
    "preview": "# 2.6 Interfaces\n\n## Interface\n\nEines der besten Sprachmerkmale von Go sind Interfaces. Nach dem Lesen dieses Abschnitts"
  },
  {
    "path": "de/02.7.md",
    "chars": 9926,
    "preview": "# 2.7 Nebenläufigkeit\n\nEs wird behauptet, Go sei das C des 21. Jahrhunderts. Ich glaube, dafür gibt es zwei Gründe: erst"
  },
  {
    "path": "de/02.8.md",
    "chars": 1789,
    "preview": "# 2.8 Zusammenfassung\n\nIn diesem Kapitel haben wir uns hauptsächlich mit den 25 Schlüsselwörtern in Go auseinandergesetz"
  },
  {
    "path": "de/03.0.md",
    "chars": 623,
    "preview": "# 3 Internet Grundlagen\n\nDer Grund warum du dieses Buch liest, ist das du lernen möchtest wie man mit Go Webanwendungen "
  },
  {
    "path": "de/03.1.md",
    "chars": 11092,
    "preview": "# Web working principles\n\nEvery time you open your browsers, type some URLs and press enter, you will see beautiful web "
  },
  {
    "path": "de/03.2.md",
    "chars": 2460,
    "preview": "# 3.2 Build a simple web server\n\nWe've discussed that web applications are based on the HTTP protocol, and Go provides f"
  },
  {
    "path": "de/03.3.md",
    "chars": 3723,
    "preview": "# 3.3 How Go works with web\n\nWe learned to use the `net/http` package to build a simple web server in the previous secti"
  },
  {
    "path": "de/03.4.md",
    "chars": 4682,
    "preview": "# 3.4 Get into http package\n\nIn previous sections, we learned about the work flow of the web and talked a little bit abo"
  },
  {
    "path": "de/03.5.md",
    "chars": 498,
    "preview": "# 3.5 Summary\n\nIn this chapter, we introduced HTTP, DNS resolution flow and how to build a simple web server. Then we ta"
  },
  {
    "path": "de/04.0.md",
    "chars": 1683,
    "preview": "# 4 User form\n\nA user form is something that is very commonly used when developping web applications. It provides the ab"
  },
  {
    "path": "de/04.1.md",
    "chars": 4524,
    "preview": "# 4.1 Process form inputs\n\nBefore we begin, let's take a look at a simple example of a typical user form, saved as `logi"
  },
  {
    "path": "de/04.2.md",
    "chars": 6149,
    "preview": "# 4.2 Verification of inputs\n\nOne of the most important principles in web development is that you cannot trust anything "
  },
  {
    "path": "de/04.3.md",
    "chars": 3154,
    "preview": "# 4.3 Cross site scripting\n\nToday's websites have much more dynamic content in order to improve user experience, which m"
  },
  {
    "path": "de/04.4.md",
    "chars": 3035,
    "preview": "# 4.4 Duplicate submissions\n\nI don't know if you've ever seen some blogs or BBS' that have more than one posts that are "
  },
  {
    "path": "de/04.5.md",
    "chars": 4983,
    "preview": "# 4.5 File upload\n\nSuppose you have a website like Instagram and you want users to upload their beautiful photos. How wo"
  },
  {
    "path": "de/04.6.md",
    "chars": 528,
    "preview": "# 4.6 Summary\n\nIn this chapter, we mainly learned how to process form data in Go through several examples like logging i"
  },
  {
    "path": "de/05.0.md",
    "chars": 1199,
    "preview": "# 5 Database\n\nFor web developers, the database is at the core of web development. You can save almost anything into a da"
  },
  {
    "path": "de/05.1.md",
    "chars": 8084,
    "preview": "# 5.1 database/sql interface\n\nGo doesn't provide any official database drivers, unlike other languages like PHP which do"
  },
  {
    "path": "de/05.2.md",
    "chars": 4156,
    "preview": "# 5.2 MySQL\n\nThe LAMP stack has been very popular on the internet in recent years, and the M in LAMP stand for MySQL. My"
  },
  {
    "path": "de/05.3.md",
    "chars": 3425,
    "preview": "# 5.3 SQLite\n\nSQLite is an open source, embedded relational database. It has a self-contained, zero-configuration and tr"
  },
  {
    "path": "de/05.4.md",
    "chars": 3654,
    "preview": "# 5.4 PostgreSQL\n\nPostgreSQL is an object-relational database management system available for many platforms including L"
  },
  {
    "path": "de/05.5.md",
    "chars": 9066,
    "preview": "# 5.5 Develop ORM based on beedb\n\n( ***Project beedb is no longer maintained, but the code s still there*** )\n\nbeedb is "
  },
  {
    "path": "de/05.6.md",
    "chars": 5002,
    "preview": "# 5.6 NoSQL database\n\nA NoSQL database provides a mechanism for the storage and retrieval of data that uses looser consi"
  },
  {
    "path": "de/05.7.md",
    "chars": 788,
    "preview": "# 5.7 Summary\n\nIn this chapter, you first learned about the design of the `database/sql` interface and many third-party "
  },
  {
    "path": "de/06.0.md",
    "chars": 1309,
    "preview": "# 6 Data storage and sessions\n\nAn important topic in web development is providing a good user experience, but the fact t"
  },
  {
    "path": "de/06.1.md",
    "chars": 7175,
    "preview": "## 6.1 Session and cookies\n\nSessions and cookies are two very common web concepts, and are also very easy to misundersta"
  },
  {
    "path": "de/06.2.md",
    "chars": 10559,
    "preview": "# 6.2 How to use sessions in Go\n\nIn section 6.1, we learned that sessions are one solution for verifying users, and that"
  },
  {
    "path": "de/06.3.md",
    "chars": 4141,
    "preview": "# 6.3 Session storage\n\nWe introduced a simple session manager's working principles in the previous section, and among ot"
  },
  {
    "path": "de/06.4.md",
    "chars": 4389,
    "preview": "# 6.4 Preventing session hijacking\n\nSession hijacking is a common yet serious security threat. Clients use session ids f"
  },
  {
    "path": "de/06.5.md",
    "chars": 917,
    "preview": "# 6.5 Summary\n\nIn this chapter, we learned about the definition and purpose of sessions and cookies, and the relationshi"
  },
  {
    "path": "de/07.0.md",
    "chars": 1354,
    "preview": "# 7 Text files\n\nHandling text files is a big part of web development. We often need to produce or handle received text c"
  },
  {
    "path": "de/07.1.md",
    "chars": 9940,
    "preview": "# 7.1 XML\n\nXML is a commonly used data communication format in web services. Today, it's assuming a more and more import"
  },
  {
    "path": "de/07.2.md",
    "chars": 8700,
    "preview": "# 7.2 JSON\n\nJSON (JavaScript Object Notation) is a lightweight data exchange language which is based on text description"
  },
  {
    "path": "de/07.3.md",
    "chars": 10052,
    "preview": "# 7.3 Regexp\n\nRegexp is a complicated but powerful tool for pattern matching and text manipulation. Although does not pe"
  },
  {
    "path": "de/07.4.md",
    "chars": 12058,
    "preview": "# 7.4 Templates\n\n## What is a template?\n\nHopefully you're aware of the MVC (Model, View, Controller) design model, where"
  },
  {
    "path": "de/07.5.md",
    "chars": 3441,
    "preview": "# 7.5 Files\n\nFiles are must-have objects on every single computer device. It won't come as any surprise to you that web "
  },
  {
    "path": "de/07.6.md",
    "chars": 4168,
    "preview": "# 7.6 Strings\n\nOn the web, almost everything we see (including user inputs, database access, etc.), is represented by st"
  },
  {
    "path": "de/07.7.md",
    "chars": 662,
    "preview": "# 7.7 Summary\n\nIn this chapter, we introduced some text processing tools like XML, JSON, Regexp and we also talked about"
  },
  {
    "path": "de/08.0.md",
    "chars": 2177,
    "preview": "# 8 Web services\n\nWeb services allow you use formats like XML or JSON to exchange information through HTTP. For example,"
  },
  {
    "path": "de/08.1.md",
    "chars": 15603,
    "preview": "# 8.1 Sockets\n\nSome network application developers say that the lower application layers are all about socket programmin"
  },
  {
    "path": "de/08.2.md",
    "chars": 6222,
    "preview": "# 8.2 WebSockets\n\nWebSockets are an important feature of HTML5. It implements browser based remote sockets, which allows"
  },
  {
    "path": "de/08.3.md",
    "chars": 8278,
    "preview": "# 8.3 REST\n\nREST is the most popular software architecture on the internet today because it is founded on well defined, "
  },
  {
    "path": "de/08.4.md",
    "chars": 10049,
    "preview": "# 8.4 RPC\n\nIn previous sections we talked about how to write network applications based on Sockets and HTTP. We learned "
  },
  {
    "path": "de/08.5.md",
    "chars": 1324,
    "preview": "# 8.5 Summary\n\nIn this chapter, I introduced you to several mainstream web application development models. In section 8."
  },
  {
    "path": "de/09.0.md",
    "chars": 2000,
    "preview": "# 9 Security and encryption\nSecurity is an extremely important aspect of most web applications. This topic has been gett"
  },
  {
    "path": "de/09.1.md",
    "chars": 6089,
    "preview": "# 9.1 CSRF attacks\n\n## What is CSRF?\n\nCSRF and XSRF both stand for \"Cross-site request forgery\". It's also known as a \"o"
  },
  {
    "path": "de/09.2.md",
    "chars": 7934,
    "preview": "# 9.2 Filtering inputs\n\nFiltering user data is one way we can improve the security of our web apps, using it to verify t"
  },
  {
    "path": "de/09.3.md",
    "chars": 6752,
    "preview": "# 9.3 XSS attacks\n\nWith the development of Internet technology, web applications are often packed with dynamic content t"
  },
  {
    "path": "de/09.4.md",
    "chars": 6734,
    "preview": "# 9.4 SQL injection\n\n## What is SQL injection\n\nSQL injection attacks are (as the name would suggest) one of the many typ"
  },
  {
    "path": "de/09.5.md",
    "chars": 6960,
    "preview": "# 9.5 Password storage\n\nOver the years, many websites have suffered from breaches in user password data. Even top intern"
  },
  {
    "path": "de/09.6.md",
    "chars": 3500,
    "preview": "# 9.6 Encrypting and decrypting data\n\nThe previous section describes how to securely store passwords, but sometimes it m"
  },
  {
    "path": "de/09.7.md",
    "chars": 1541,
    "preview": "# 9.7 Summary\n\nIn this chapter, we've described CSRF, XSS and SQL injection based attacks. Most web applications are vul"
  },
  {
    "path": "de/10.0.md",
    "chars": 2803,
    "preview": "# 10 Internationalization and localization\n\nIn order to adapt to the increasing globalization of the internet, as develo"
  },
  {
    "path": "de/10.1.md",
    "chars": 7681,
    "preview": "# 10.1 Setting the default region\n\n## Finding out the locale\n\nA locale is a set of descriptors for a particular geograph"
  },
  {
    "path": "de/10.2.md",
    "chars": 7186,
    "preview": "# 10.2 Localized Resources\n\nThe previous section described how to set locales. After the locale has been set, we then ne"
  },
  {
    "path": "de/10.3.md",
    "chars": 6301,
    "preview": "# 10.3 International sites\n\nThe previous section explained how to deal with localized resources, namely by using locale "
  },
  {
    "path": "de/10.4.md",
    "chars": 831,
    "preview": "# 10.4 Summary\n\nThrough this introductory chapter on i18n, you should now be familiar with some of the steps and process"
  },
  {
    "path": "de/11.0.md",
    "chars": 2947,
    "preview": "# 11 Error Handling, Debugging, and Testing\n\nWe often see the majority of a programmer's \"programming\" time spent on che"
  },
  {
    "path": "de/11.1.md",
    "chars": 10178,
    "preview": "# 11.1 Error handling\n\nGo's major design considerations are rooted in the following ideas: a simple, clear, and concise "
  },
  {
    "path": "de/11.2.md",
    "chars": 10822,
    "preview": "# 11.2 Debugging with GDB\n\nDuring the development process of any application, developers will always need to perform som"
  },
  {
    "path": "de/11.3.md",
    "chars": 7792,
    "preview": "# 11.3 Writing test cases\n\nIn the course of development, a very important step is to test our code to ensure its quality"
  },
  {
    "path": "de/11.4.md",
    "chars": 1152,
    "preview": "# 11.4 Summary\n\nOver the course of the last three sections, we've introduced how to handle errors in Go, first looking a"
  },
  {
    "path": "de/12.0.md",
    "chars": 1269,
    "preview": "# 12 Deployment and maintenance\n\nSo far, we've covered the basics of developing, debugging and testing web applications "
  },
  {
    "path": "de/12.1.md",
    "chars": 9338,
    "preview": "# 12.1 Logs\n\nWe want to build web applications that can keep track of events which have occurred throughout execution, c"
  },
  {
    "path": "de/12.2.md",
    "chars": 11951,
    "preview": "# 12.2 Errors and crashes\n\nOnce our web applications go live, it's likely that there will be some unforeseen errors. A f"
  },
  {
    "path": "de/12.3.md",
    "chars": 8833,
    "preview": "# 12.3 Deployment\n\nWhen our web application is finally production ready, what are the steps necessary to get it deployed"
  },
  {
    "path": "de/12.4.md",
    "chars": 13596,
    "preview": "# 12.4 Backup and recovery\n\nIn this section, we'll discuss another aspect of application management: data backup and rec"
  },
  {
    "path": "de/12.5.md",
    "chars": 1210,
    "preview": "# 12.5 Summary\n\nIn this chapter, we discussed how to deploy and maintain our Go web applications. We also looked at some"
  },
  {
    "path": "de/13.0.md",
    "chars": 2101,
    "preview": "# 13 Building a web framework\n\nThe Preceding twelve chapters describe how to develop web applications in Go, introducing"
  },
  {
    "path": "de/13.1.md",
    "chars": 4853,
    "preview": "# 13.1 Project planning\n\nAnything you intend to do well must first be planned well. In our case, our intention is to dev"
  },
  {
    "path": "de/13.2.md",
    "chars": 9834,
    "preview": "# 13.2 Customizing routers\n\n## HTTP routing\n\nThe HTTP routing component is responsible for mapping HTTP requests to a co"
  },
  {
    "path": "de/13.3.md",
    "chars": 7419,
    "preview": "# 13.3 Designing controllers\n\nMost traditional MVC frameworks are based on suffix action mapping. Nowadays, the REST sty"
  },
  {
    "path": "de/13.4.md",
    "chars": 8923,
    "preview": "# 13.4 Logging and configuration\n\n## The importance of logging and configuration\n\nPreviously in the book, we saw that ev"
  },
  {
    "path": "de/13.5.md",
    "chars": 5117,
    "preview": "# 13.5 Adding, deleting and updating blogs\n\nWe've already introduced the entire concept behind the Beego framework throu"
  },
  {
    "path": "de/13.6.md",
    "chars": 1123,
    "preview": "# 13.6 Summary\n\n\nIn this chapter, we described how to implement the major components of a Go web framework. We first des"
  },
  {
    "path": "de/14.0.md",
    "chars": 1744,
    "preview": "# 14 Developing a web framework\n\nChapter 13 described how to develop a web framework in Go. We introduced the MVC archit"
  },
  {
    "path": "de/14.1.md",
    "chars": 3710,
    "preview": "# 14.1 Static files\n\nWe've already talked about how to deal with static files in previous sections. Now, let's look at h"
  },
  {
    "path": "de/14.2.md",
    "chars": 3613,
    "preview": "# 14.2 Sessions\n\nIn chapter 6, we introduced some basic concepts pertaining to sessions in Go, and we implemented a sess"
  },
  {
    "path": "de/14.3.md",
    "chars": 11439,
    "preview": "# 14.3 Forms\n\nIn web development, the following workflow will probably look quite familiar: \n\n- Open a web page showing "
  },
  {
    "path": "de/14.4.md",
    "chars": 8269,
    "preview": "# 14.4 User validation\n\nIn the process of developping web applications, user authentication is a problem which developer"
  },
  {
    "path": "de/14.5.md",
    "chars": 3051,
    "preview": "# 14.5 Multi-language support\n\nIn the chapter where we introduced internationalization and localization, we developed th"
  },
  {
    "path": "de/14.6.md",
    "chars": 3409,
    "preview": "# 14.6 pprof\n\nA great feature of Go's standard library is its code performance monitoring tools. These packages exist in"
  },
  {
    "path": "de/14.7.md",
    "chars": 1809,
    "preview": "# 14.7 Summary\n\nThis chapter illustrates some ways in which the Beego framework can be extended. We first looked at stat"
  },
  {
    "path": "de/README.md",
    "chars": 1971,
    "preview": "***Erstelle Webanwendungen mit Go***\n======================================\n\n### Absicht\n\nWeil ich an der Entwicklung vo"
  },
  {
    "path": "de/SUMMARY.md",
    "chars": 2829,
    "preview": "* [Go Environment Configuration](01.0.md)\n\t* [Installation](01.1.md)\n\t* [$GOPATH and workspace](01.2.md)\n\t* [Go commands"
  },
  {
    "path": "de/code/readme.md",
    "chars": 250,
    "preview": "## Workspace setup.\n\nTo avoid workspace issues and be able to develop from any folder within this path,\nset the environm"
  },
  {
    "path": "de/code/src/apps/ch.1.2/main.go",
    "chars": 439,
    "preview": "// Example code for Chapter 1.2 from \"Build Web Application with Golang\"\r\n// Purpose: Run this file to check if your wor"
  },
  {
    "path": "de/code/src/apps/ch.2.1/main.go",
    "chars": 373,
    "preview": "// Example code for Chapter ? from \"Build Web Application with Golang\"\n// Purpose: Hello world example demonstrating UTF"
  },
  {
    "path": "de/code/src/apps/ch.2.2/main.go",
    "chars": 8073,
    "preview": "// Example code for Chapter 2.2 from \"Build Web Application with Golang\"\n// Purpose: Goes over the assignment and manipu"
  },
  {
    "path": "de/code/src/apps/ch.2.2/what_is_wrong_with_this/main.go",
    "chars": 197,
    "preview": "// Example code for Chapter 2.2 from \"Build Web Application with Golang\"\n// Purpose: Try to fix this program.\n// From th"
  },
  {
    "path": "de/code/src/apps/ch.2.3/basic_functions/main.go",
    "chars": 550,
    "preview": "// Example code for Chapter 2.3 from \"Build Web Application with Golang\"\n// Purpose: Creating a basic function\npackage m"
  },
  {
    "path": "de/code/src/apps/ch.2.3/hidden_print_methods/main.go",
    "chars": 307,
    "preview": "// As of Google go 1.1.2, `println()` and `print()` are hidden functions included from the runtime package.\n// However i"
  },
  {
    "path": "de/code/src/apps/ch.2.3/import_packages/main.go",
    "chars": 1043,
    "preview": "// Example code for Chapter 2.3 from \"Build Web Application with Golang\"\n// Purpose: Shows different ways of importing a"
  },
  {
    "path": "de/code/src/apps/ch.2.3/import_packages/only_call_init/only_call_init.go",
    "chars": 104,
    "preview": "package only_call_init\n\nimport \"fmt\"\n\nfunc init() {\n\tfmt.Println(\"only_call_init.init() was called.\")\n}\n"
  },
  {
    "path": "de/code/src/apps/ch.2.3/main.go",
    "chars": 2857,
    "preview": "// Example code for Chapter 2.3 from \"Build Web Application with Golang\"\n// Purpose: Goes over if, else, switch conditio"
  },
  {
    "path": "de/code/src/apps/ch.2.3/panic_and_recover/main.go",
    "chars": 610,
    "preview": "// Example code for Chapter 2.3 from \"Build Web Application with Golang\"\n// Purpose: Showing how to use `panic()` and `r"
  },
  {
    "path": "de/code/src/apps/ch.2.3/pass_by_value_and_pointer/main.go",
    "chars": 665,
    "preview": "// Example code for Chapter 2.3 from \"Build Web Application with Golang\"\n// Purpose: Shows passing a variable by value a"
  },
  {
    "path": "de/code/src/apps/ch.2.3/type_function/main.go",
    "chars": 939,
    "preview": "// Example code for Chapter 2.3 from \"Build Web Application with Golang\"\n// Purpose: Shows how to define a function type"
  },
  {
    "path": "de/code/src/apps/ch.2.3/variadic_functions/main.go",
    "chars": 431,
    "preview": "// Example code for Chapter 2.3 from \"Build Web Application with Golang\"\n// Purpose: Shows how to return multiple values"
  },
  {
    "path": "de/code/src/apps/ch.2.4/compare_age/main.go",
    "chars": 1109,
    "preview": "// Example code for Chapter 2.4 from \"Build Web Application with Golang\"\n// Purpose: Shows you how to pass and use struc"
  },
  {
    "path": "de/code/src/apps/ch.2.4/embedded_structs/main.go",
    "chars": 997,
    "preview": "// Example code for Chapter 2.4 from \"Build Web Application with Golang\"\n// Purpose: Example of embedded fields\npackage "
  },
  {
    "path": "de/code/src/apps/ch.2.4/embedded_structs2/main.go",
    "chars": 1066,
    "preview": "// Example code for Chapter 2.4 from \"Build Web Application with Golang\"\n// Purpose: Another example of embedded fields\n"
  },
  {
    "path": "de/code/src/apps/ch.2.4/embedded_structs_with_name_conflict/main.go",
    "chars": 593,
    "preview": "// Example code for Chapter 2.4 from \"Build Web Application with Golang\"\n// Purpose: Shows a name conflict with a embedd"
  },
  {
    "path": "de/code/src/apps/ch.2.4/main.go",
    "chars": 928,
    "preview": "// Example code for Chapter 2.4 from \"Build Web Application with Golang\"\n// Purpose: Shows different ways of creating a "
  },
  {
    "path": "de/code/src/apps/ch.2.5/attach_methods_to_struct/main.go",
    "chars": 604,
    "preview": "// Example code from Chapter 2.5\n// Attach method to struct.\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\ntype Rectangle str"
  },
  {
    "path": "de/code/src/apps/ch.2.5/box_example/main.go",
    "chars": 1401,
    "preview": "package main\n\nimport \"fmt\"\n\nconst (\n\tWHITE = iota\n\tBLACK\n\tBLUE\n\tRED\n\tYELLOW\n)\n\ntype Color byte\n\ntype Box struct {\n\twidth"
  },
  {
    "path": "de/code/src/apps/ch.2.5/embedded_method/main.go",
    "chars": 531,
    "preview": "package main\nimport \"fmt\"\n\ntype Human struct {\n    name string\n    age int\n    phone string\n}\n\ntype Student struct {\n   "
  },
  {
    "path": "de/code/src/apps/ch.2.5/method_overload/main.go",
    "chars": 610,
    "preview": "package main\n\nimport \"fmt\"\n\ntype Human struct {\n\tname  string\n\tage   int\n\tphone string\n}\n\ntype Student struct {\n\tHuman\n\t"
  },
  {
    "path": "de/code/src/apps/ch.2.5/pass_struct_to_method/main.go",
    "chars": 288,
    "preview": "package main\n\nimport \"fmt\"\n\ntype Rectangle struct {\n\twidth, height float64\n}\n\nfunc area(r Rectangle) float64 {\n\treturn r"
  },
  {
    "path": "de/code/src/apps/ch.2.6/interface/main.go",
    "chars": 1600,
    "preview": "package main\nimport \"fmt\"\n\ntype Human struct {\n    name string\n    age int\n    phone string\n}\n\ntype Student struct {\n   "
  },
  {
    "path": "de/code/src/apps/ch.2.6/reflection/main.go",
    "chars": 631,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n)\n\nfunc show_interface_none() {\n\tfmt.Println(\"\\nshow_interface_none()\")\n\tvar a "
  },
  {
    "path": "de/code/src/apps/ch.2.6/stringer_interface/main.go",
    "chars": 360,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n)\n\ntype Human struct {\n\tname  string\n\tage   int\n\tphone string\n}\n\n// Human imple"
  },
  {
    "path": "de/code/src/apps/ch.2.6/switch_type_check/main.go",
    "chars": 891,
    "preview": "package main\n\nimport (\n    \"fmt\"\n    \"strconv\"\n)\n\ntype Element interface{}\ntype List []Element\n\ntype Person struct {\n   "
  },
  {
    "path": "de/code/src/apps/ch.2.6/type_check/main.go",
    "chars": 947,
    "preview": "package main\n\nimport (\n    \"fmt\"\n    \"strconv\"\n)\n\ntype Element interface{}\ntype List []Element\n\ntype Person struct {\n   "
  },
  {
    "path": "de/code/src/apps/ch.2.7/buffered_channel/main.go",
    "chars": 297,
    "preview": "// Example code for Chapter 2.7 from \"Build Web Application with Golang\"\n// Purpose: Shows how to use a buffered channel"
  },
  {
    "path": "de/code/src/apps/ch.2.7/goroutine/main.go",
    "chars": 356,
    "preview": "// Example code for Chapter 2.7 from \"Build Web Application with Golang\"\n// Purpose: Shows how to launch a simple goroun"
  },
  {
    "path": "de/code/src/apps/ch.2.7/range_and_close_channel/main.go",
    "chars": 391,
    "preview": "// Example code for Chapter 2.7 from \"Build Web Application with Golang\"\n// Purpose: Shows how to close and interate thr"
  },
  {
    "path": "de/code/src/apps/ch.2.7/select_channel/main.go",
    "chars": 459,
    "preview": "// Example code for Chapter 2.7 from \"Build Web Application with Golang\"\n// Purpose: Shows how to use `select`\npackage m"
  },
  {
    "path": "de/code/src/apps/ch.2.7/timeout/main.go",
    "chars": 403,
    "preview": "// Example code for Chapter 2.7 from \"Build Web Application with Golang\"\n// Purpose: Shows how to create and use a timeo"
  },
  {
    "path": "de/code/src/apps/ch.2.7/unbuffered_channel/main.go",
    "chars": 459,
    "preview": "// Example code for Chapter 2.7 from \"Build Web Application with Golang\"\n// Purpose: Shows how to create and use a unbuf"
  },
  {
    "path": "de/code/src/apps/ch.3.2/main.go",
    "chars": 854,
    "preview": "// Example code for Chapter 3.2 from \"Build Web Application with Golang\"\n// Purpose: Shows how to acces the form values "
  },
  {
    "path": "de/code/src/apps/ch.3.4/main.go",
    "chars": 593,
    "preview": "// Example code for Chapter 3.4 from \"Build Web Application with Golang\"\n// Purpose: Shows how to create a handler for `"
  },
  {
    "path": "de/code/src/apps/ch.4.1/login.gtpl",
    "chars": 248,
    "preview": "<html>\n<head>\n<title></title>\n</head>\n<body>\n<form action=\"/login\" method=\"post\">\n    Username:<input type=\"text\" name=\""
  },
  {
    "path": "de/code/src/apps/ch.4.1/main.go",
    "chars": 1486,
    "preview": "// Example code for Chapter 4.1 from \"Build Web Application with Golang\"\n// Purpose: Shows how to create a simple login "
  },
  {
    "path": "de/code/src/apps/ch.4.2/main.go",
    "chars": 1682,
    "preview": "// Example code for Chapter 4.2 from \"Build Web Application with Golang\"\n// Purpose: Shows how to perform server-side va"
  },
  {
    "path": "de/code/src/apps/ch.4.2/profile.gtpl",
    "chars": 2740,
    "preview": "{{define \"profile\"}}<!DOCTYPE html>\n<html>\n\t<style>\n\t.row{\n\t\tdisplay: table-row;\n\t}\n\t.cell{\n\t\tdisplay: table-cell;\n\t}\n\t."
  },
  {
    "path": "de/code/src/apps/ch.4.2/submission.gtpl",
    "chars": 238,
    "preview": "{{define \"submission\"}}<!DOCTYPE html>\n<html>\n\t<body>\n\t\t{{if .Errors}}\n\t\t<h2>Errors:</h2>\n\t\t\t<ol>\n\t\t\t\t{{range .Errors}}\t"
  },
  {
    "path": "de/code/src/apps/ch.4.2/validator/main.go",
    "chars": 4238,
    "preview": "// This file contains all the validators to validate the profile page.\npackage validator\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"ne"
  },
  {
    "path": "de/code/src/apps/ch.4.3/index.gtpl",
    "chars": 648,
    "preview": "<!doctype html>\n<html>\n\t<body>\n\t\t<h2>Cross Site Scripting Attack Test</h2>\n\t\t{{if .}}\n\t\tPrevious User Input: <br/>\n\t\t\n\t\t"
  },
  {
    "path": "de/code/src/apps/ch.4.3/main.go",
    "chars": 1127,
    "preview": "// Example code for Chapter 4.3 from \"Build Web Application with Golang\"\n// Purpose: Shows how to properly escape input\n"
  },
  {
    "path": "de/code/src/apps/ch.4.4/main.go",
    "chars": 1486,
    "preview": "// Example code for Chapter 3.2 from \"Build Web Application with Golang\"\n// Purpose: Shows how to prevent duplicate subm"
  },
  {
    "path": "de/code/src/apps/ch.4.4/nonce/main.go",
    "chars": 1416,
    "preview": "// A nonce is a number or string used only once.\n// This is useful for generating a unique token for login pages to prev"
  },
  {
    "path": "de/code/src/apps/ch.4.4/profile.gtpl",
    "chars": 2685,
    "preview": "{{define \"profile\"}}<!DOCTYPE html>\n<html>\n\t<style>\n\t.row{\n\t\tdisplay: table-row;\n\t}\n\t.cell{\n\t\tdisplay: table-cell;\n\t}\n\t."
  },
  {
    "path": "de/code/src/apps/ch.4.4/submission.gtpl",
    "chars": 302,
    "preview": "{{define \"submission\"}}<!DOCTYPE html>\n<html>\n\t<body>\n\t\t{{if .Errors}}\n\t\t<h2>Errors:</h2>\n\t\t\t<ol>\n\t\t\t\t{{range .Errors}}\t"
  },
  {
    "path": "de/code/src/apps/ch.4.4/validator/main.go",
    "chars": 4238,
    "preview": "// This file contains all the validators to validate the profile page.\npackage validator\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"ne"
  },
  {
    "path": "de/code/src/apps/ch.4.5/client_upload/main.go",
    "chars": 885,
    "preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc checkError(err err"
  },
  {
    "path": "de/code/src/apps/ch.4.5/index.gtpl",
    "chars": 357,
    "preview": "{{define \"index\"}}\n<!doctype html>\n<html>\n<head>\n    <title>Upload file</title>\n</head>\n<body>\n<form enctype=\"multipart/"
  },
  {
    "path": "de/code/src/apps/ch.4.5/main.go",
    "chars": 1606,
    "preview": "// Example code for Chapter 4.5\n// Purpose is to create a server to handle uploading files.\npackage main\n\nimport (\n\t\"app"
  },
  {
    "path": "de/code/src/apps/ch.4.5/nonce/main.go",
    "chars": 1416,
    "preview": "// A nonce is a number or string used only once.\n// This is useful for generating a unique token for login pages to prev"
  },
  {
    "path": "de/code/src/apps/ch.4.5/upload.gtpl",
    "chars": 295,
    "preview": "{{define \"upload\"}}<!DOCTYPE html>\n<html>\n\t<body>\n\t\t{{if .Errors}}\n\t\t<h2>Errors:</h2>\n\t\t\t<ol>\n\t\t\t\t{{range .Errors}}\t\n\t\t\t"
  },
  {
    "path": "de/code/src/apps/ch.4.5/validator/main.go",
    "chars": 4238,
    "preview": "// This file contains all the validators to validate the profile page.\npackage validator\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"ne"
  },
  {
    "path": "de/code/src/apps/ch.5.2/main.go",
    "chars": 1700,
    "preview": "// Example code for Chapter 5.2 from \"Build Web Application with Golang\"\n// Purpose: Use SQL driver to perform simple CR"
  },
  {
    "path": "de/code/src/apps/ch.5.2/readme.md",
    "chars": 377,
    "preview": "## Setup for `ch.5.2`\n\n- Step 1) Install and run MySql\n- Step 2) Create a user and database according to the constants i"
  },
  {
    "path": "de/code/src/apps/ch.5.2/schema.sql",
    "chars": 233,
    "preview": "CREATE TABLE `userinfo` (\n\t    `uid` INT(10) NOT NULL AUTO_INCREMENT,\n\t    `username` VARCHAR(64) NULL DEFAULT NULL,\n\t  "
  },
  {
    "path": "de/code/src/apps/ch.5.3/main.go",
    "chars": 1624,
    "preview": "// Example code for Chapter 5.3 from \"Build Web Application with Golang\"\n// Purpose: Shows how to run simple CRUD operat"
  },
  {
    "path": "de/code/src/apps/ch.5.3/readme.md",
    "chars": 459,
    "preview": "## Set up for `ch.5.3`\n\n- Step 1) Download and install sqlite 3.\n- Step 2) Run `sqlite3 foo.db` to create a databased ca"
  },
  {
    "path": "de/code/src/apps/ch.5.3/schema.sql",
    "chars": 163,
    "preview": "CREATE TABLE `userinfo` (\n\t\t\t`uid` INTEGER PRIMARY KEY AUTOINCREMENT,\n\t\t\t`username` VARCHAR(64) NULL,\n\t\t\t`department` VA"
  },
  {
    "path": "de/code/src/apps/ch.5.4/main.go",
    "chars": 1791,
    "preview": "// Example code for Chapter 5.4 from \"Build Web Application with Golang\"\n// Purpose: Show how to perform CRUD operations"
  },
  {
    "path": "de/code/src/apps/ch.5.4/readme.md",
    "chars": 379,
    "preview": "## Setup for ch.5.4\n\n- Step 1) Install and run Postgres\n- Step 2) Create a user and database according to the constants "
  },
  {
    "path": "de/code/src/apps/ch.5.4/schema.sql",
    "chars": 234,
    "preview": "CREATE TABLE userinfo\n(\n\t    uid serial NOT NULL,\n\t    username character varying(100) NOT NULL,\n\t    departname charact"
  },
  {
    "path": "de/code/src/apps/ch.5.5/main.go",
    "chars": 4167,
    "preview": "// Example code for Chapter 5.5\n// Purpose is to show to use BeeDB ORM for basic CRUD operations for sqlite3\npackage mai"
  },
  {
    "path": "de/code/src/apps/ch.5.5/readme.md",
    "chars": 464,
    "preview": "## Set up for `ch.5.5`\n\n- Step 1) Download and install sqlite 3.\n- Step 2) Run `sqlite3 foo.db` to create a databased ca"
  },
  {
    "path": "de/code/src/apps/ch.5.5/schema.sql",
    "chars": 269,
    "preview": "CREATE TABLE `userinfo` (\n\t`uid` INTEGER PRIMARY KEY AUTOINCREMENT,\n\t`username` VARCHAR(64) NULL,\n\t`department` VARCHAR("
  },
  {
    "path": "de/code/src/apps/ch.5.6/mongodb/main.go",
    "chars": 1100,
    "preview": "// Example code for Chapter 5.6 from \"Build Web Application with Golang\"\n// Purpose: Shows you have to perform basic CRU"
  },
  {
    "path": "de/code/src/apps/ch.5.6/mongodb/readme.md",
    "chars": 255,
    "preview": "## Setup for `ch.5.6` for MongoDB\n\n- Step 1) Install and run MongoDB\n- Step 2) Launch the MongoDB daemon (mongod) to sta"
  },
  {
    "path": "de/code/src/apps/ch.5.6/redis/main.go",
    "chars": 1175,
    "preview": "// Example code for Chapter 5.6 from \"Build Web Application with Golang\"\n// Purpose: Shows you have to perform basic CRU"
  },
  {
    "path": "de/code/src/apps/ch.5.6/redis/readme.md",
    "chars": 291,
    "preview": "## Setup for `ch.5.6` for Redis\n\n- Step 1) Install and run Redis\n- Step 2) Launch the Redis server matching the DB const"
  },
  {
    "path": "de/code/src/mymath/sqrt.go",
    "chars": 340,
    "preview": "// Example code for Chapter 1.2 from \"Build Web Application with Golang\"\r\n// Purpose: Shows how to create a simple packa"
  },
  {
    "path": "de/preface.md",
    "chars": 3262,
    "preview": "- 1.[Go environment configuration](01.0.md)\n\t- 1.1. [Installation](01.1.md)\n\t- 1.2. [$GOPATH and workspace](01.2.md)\n\t- "
  },
  {
    "path": "de/ref.md",
    "chars": 778,
    "preview": "# Anhang A Literaturverzeichnis\n\nDieses Buch ist eine Zusammenfassung meiner Erfahrungen in Go. Einige Inhalte stammen a"
  },
  {
    "path": "en/01.0.md",
    "chars": 1552,
    "preview": "# 1 Go Environment Configuration\n\nWelcome to the world of Go, let's start exploring!\n\nGo is a fast-compiled, garbage-col"
  },
  {
    "path": "en/01.1.md",
    "chars": 7474,
    "preview": "# 1.1 Installation\n\n## Three ways to install Go\n\nThere are many ways to configure the Go development environment on your"
  },
  {
    "path": "en/01.2.md",
    "chars": 6685,
    "preview": "# 1.2 $GOPATH and workspace\n\n## $GOPATH\n\nGo takes a unique approach to manage the code files with the introduction of a "
  },
  {
    "path": "en/01.3.md",
    "chars": 6641,
    "preview": "# 1.3 Go commands\n\n## Go commands\n\nThe Go language comes with a complete set of command operation tools. You can execute"
  },
  {
    "path": "en/01.4.md",
    "chars": 16835,
    "preview": "# Go development tools\n\nIn this section, I'm going to show you a few IDEs that can help you become a more efficient prog"
  },
  {
    "path": "en/01.5.md",
    "chars": 800,
    "preview": "# 1.5 Summary\n\nIn this chapter, we talked about how to install Go using three different methods including from source co"
  },
  {
    "path": "en/02.0.md",
    "chars": 978,
    "preview": "# 2 Go basic knowledge\n\nGo is a compiled system programming language, and it belongs to the C-family. However, its compi"
  },
  {
    "path": "en/02.1.md",
    "chars": 10166,
    "preview": "## What makes Go different from other languages?\n\nThe Go programming language was created with one goal in mind, to be a"
  },
  {
    "path": "en/02.2.md",
    "chars": 17934,
    "preview": "# 2.2 Go foundation\n\nIn this section, we are going to teach you how to define constants, variables with elementary types"
  },
  {
    "path": "en/02.3.md",
    "chars": 18049,
    "preview": "# 2.3 Control statements and functions\n\nIn this section, we are going to talk about control statements and function oper"
  },
  {
    "path": "en/02.4.md",
    "chars": 5773,
    "preview": "# 2.4 struct\n\n## struct\n\nWe can define new types of containers of other properties or fields in Go just like in other pr"
  },
  {
    "path": "en/02.5.md",
    "chars": 8983,
    "preview": "# Object-oriented\n\nWe talked about functions and structs in the last two sections, but did you ever consider using funct"
  },
  {
    "path": "en/02.6.md",
    "chars": 12416,
    "preview": "# 2.6 Interface\n\n## Interface\n\nOne of the subtlest design features in Go are interfaces. After reading this section, you"
  },
  {
    "path": "en/02.7.md",
    "chars": 7395,
    "preview": "# Concurrency\n\nIt is said that Go is the C of the 21st century. I think there are two reasons for it. First, Go is a sim"
  },
  {
    "path": "en/02.8.md",
    "chars": 1458,
    "preview": "# 2.8 Summary\n\nIn this chapter, we mainly introduced the 25 Go keywords. Let's review what they are and what they do.\n``"
  },
  {
    "path": "en/03.0.md",
    "chars": 565,
    "preview": "# 3 Web foundation\n\nThe reason you are reading this book is that you want to learn to build web applications in Go. As I"
  },
  {
    "path": "en/03.1.md",
    "chars": 11104,
    "preview": "# Web working principles\n\nEvery time you open your browsers, type some URLs and press enter, you will see beautiful web "
  },
  {
    "path": "en/03.2.md",
    "chars": 2489,
    "preview": "# 3.2 Build a simple web server\n\nWe've discussed that web applications are based on the HTTP protocol, and Go provides f"
  },
  {
    "path": "en/03.3.md",
    "chars": 3701,
    "preview": "# 3.3 How Go works with web\n\nWe learned to use the `net/http` package to build a simple web server in the previous secti"
  },
  {
    "path": "en/03.4.md",
    "chars": 7858,
    "preview": "# 3.4 Get into http package\n\nIn previous sections, we learned about the work flow of the web and talked a little bit abo"
  },
  {
    "path": "en/03.5.md",
    "chars": 498,
    "preview": "# 3.5 Summary\n\nIn this chapter, we introduced HTTP, DNS resolution flow and how to build a simple web server. Then we ta"
  }
]

// ... and 1609 more files (download for full content)

About this extraction

This page contains the full source code of the astaxie/build-web-application-with-golang GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1809 files (4.4 MB), approximately 1.2M tokens, and a symbol index with 1472 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

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

Copied to clipboard!