From eab1d98ba809a394fb12517776c71e10f8cbd708 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Tue, 3 Mar 2015 12:25:25 -0500 Subject: [PATCH] update book code --- eBook/examples/chapter_10/embed_func1.go | 43 + eBook/examples/chapter_10/embed_func2.go | 38 + eBook/examples/chapter_10/embedd_struct.go | 18 + eBook/examples/chapter_10/main.go | 16 + eBook/examples/chapter_10/method1.go | 29 + eBook/examples/chapter_10/method2.go | 16 + eBook/examples/chapter_10/method3.go | 24 + eBook/examples/chapter_10/method4.go | 28 + eBook/examples/chapter_10/method_on_time.go | 25 + eBook/examples/chapter_10/method_string.go | 27 + eBook/examples/chapter_10/methodset1.go | 22 + eBook/examples/chapter_10/mult_inheritance.go | 34 + eBook/examples/chapter_10/new_make.go | 27 + eBook/examples/chapter_10/person.go | 41 + eBook/examples/chapter_10/person2.go | 17 + eBook/examples/chapter_10/pointer_value.go | 28 + .../examples/chapter_10/struct_conversions.go | 24 + .../chapter_10/struct_pack/structPack.go | 6 + eBook/examples/chapter_10/struct_tag.go | 30 + .../chapter_10/structs_anonymous_fields.go | 34 + eBook/examples/chapter_10/structs_fields.go | 23 + eBook/examples/chapter_10/use_person2.go | 14 + eBook/examples/chapter_10/vcard.json | 1 + eBook/examples/chapter_11/cars.go | 95 ++ eBook/examples/chapter_11/duck_dance.go | 32 + eBook/examples/chapter_11/empty_interface.go | 38 + eBook/examples/chapter_11/emptyint_switch.go | 32 + eBook/examples/chapter_11/interfaces.go | 30 + eBook/examples/chapter_11/interfaces_poly.go | 45 + eBook/examples/chapter_11/methodset2.go | 48 + .../chapter_11/multi_interfaces_poly.go | 65 ++ eBook/examples/chapter_11/node_structures.go | 31 + eBook/examples/chapter_11/print.go | 43 + eBook/examples/chapter_11/reflect1.go | 32 + eBook/examples/chapter_11/reflect2.go | 33 + eBook/examples/chapter_11/reflect_struct.go | 47 + eBook/examples/chapter_11/reflect_struct2.go | 31 + eBook/examples/chapter_11/sort/sort.go | 58 ++ eBook/examples/chapter_11/sortmain.go | 82 ++ eBook/examples/chapter_11/static.go | 23 + .../hg/.hg/00changelog.i | Bin 0 -> 57 bytes .../tideland-cgl.googlecode.com/hg/.hg/branch | 1 + .../hg/.hg/branchheads.cache | 2 + .../hg/.hg/dirstate | Bin 0 -> 324 bytes .../tideland-cgl.googlecode.com/hg/.hg/hgrc | 2 + .../hg/.hg/requires | 4 + .../hg/.hg/store/00changelog.i | Bin 0 -> 20111 bytes .../hg/.hg/store/00manifest.i | Bin 0 -> 21201 bytes .../hg/.hg/store/data/_l_i_c_e_n_s_e.txt.i | Bin 0 -> 965 bytes .../hg/.hg/store/data/_makefile.i | Bin 0 -> 1364 bytes .../hg/.hg/store/data/cgl.go.i | Bin 0 -> 7624 bytes .../hg/.hg/store/data/cgl__test.go.i | Bin 0 -> 9376 bytes .../hg/.hg/store/data/cglctb.go.i | Bin 0 -> 1936 bytes .../hg/.hg/store/data/cglctb/_makefile.i | Bin 0 -> 803 bytes .../hg/.hg/store/data/cglctb/cglctb.go.i | Bin 0 -> 3519 bytes .../.hg/store/data/cglctb/cglctb__test.go.i | Bin 0 -> 2261 bytes .../store/data/cgldoc/_l_i_c_e_n_s_e.txt.i | Bin 0 -> 856 bytes .../hg/.hg/store/data/cgleca/_makefile.i | Bin 0 -> 976 bytes .../hg/.hg/store/data/cgleca/cgleca.go.i | Bin 0 -> 16679 bytes .../.hg/store/data/cgleca/cgleca__test.go.i | Bin 0 -> 10665 bytes .../hg/.hg/store/data/cgleca/cglecaucb.go.i | Bin 0 -> 6255 bytes .../hg/.hg/store/data/cgleca/cglecauep.go.i | Bin 0 -> 4488 bytes .../hg/.hg/store/data/cgleca/cglecautl.go.i | Bin 0 -> 3414 bytes .../hg/.hg/store/data/cglfsm.go.i | Bin 0 -> 2731 bytes .../hg/.hg/store/data/cglfsm/_makefile.i | Bin 0 -> 744 bytes .../hg/.hg/store/data/cglfsm/cglfsm.go.i | Bin 0 -> 6017 bytes .../.hg/store/data/cglfsm/cglfsm__test.go.i | Bin 0 -> 4254 bytes .../hg/.hg/store/data/cglmon.go.i | Bin 0 -> 7895 bytes .../hg/.hg/store/data/cglmon/_makefile.i | Bin 0 -> 910 bytes .../hg/.hg/store/data/cglmon/cglmon.go.i | Bin 0 -> 1910 bytes .../.hg/store/data/cglmon/cglmon__test.go.i | Bin 0 -> 2172 bytes .../hg/.hg/store/data/cglmon/cglmonetm.go.i | Bin 0 -> 5188 bytes .../hg/.hg/store/data/cglmon/cglmonssi.go.i | Bin 0 -> 5118 bytes .../hg/.hg/store/data/cglmrp.go.i | Bin 0 -> 2370 bytes .../hg/.hg/store/data/cglnum.go.i | Bin 0 -> 4157 bytes .../hg/.hg/store/data/cglnum/_makefile.i | Bin 0 -> 400 bytes .../hg/.hg/store/data/cglnum/cglnum.go.i | Bin 0 -> 2802 bytes .../.hg/store/data/cglnum/cglnum__test.go.i | Bin 0 -> 1893 bytes .../hg/.hg/store/data/cglnum/cglnumgra.go.i | Bin 0 -> 2326 bytes .../hg/.hg/store/data/cglnum/cglnumsta.go.i | Bin 0 -> 1708 bytes .../hg/.hg/store/data/cglred/_makefile.i | Bin 0 -> 593 bytes .../hg/.hg/store/data/cglred/cglred.go.i | Bin 0 -> 9610 bytes .../.hg/store/data/cglred/cglred__test.go.i | Bin 0 -> 6348 bytes .../hg/.hg/store/data/cglred/cglredcmd.go.i | Bin 0 -> 1281 bytes .../hg/.hg/store/data/cglred/cglredres.go.i | Bin 0 -> 2951 bytes .../hg/.hg/store/data/cglred/cglredurp.go.i | Bin 0 -> 4176 bytes .../hg/.hg/store/data/cglsml.go.i | Bin 0 -> 3280 bytes .../hg/.hg/store/data/cglsml/_makefile.i | Bin 0 -> 486 bytes .../hg/.hg/store/data/cglsml/cglsml.go.i | Bin 0 -> 3498 bytes .../.hg/store/data/cglsml/cglsml__test.go.i | Bin 0 -> 2207 bytes .../hg/.hg/store/data/cglsml/cglsmlpap.go.i | Bin 0 -> 3061 bytes .../hg/.hg/store/data/cglsmr.go.i | Bin 0 -> 3454 bytes .../hg/.hg/store/data/cglsrt.go.i | Bin 0 -> 1803 bytes .../hg/.hg/store/data/cglsup.go.i | Bin 0 -> 2666 bytes .../hg/.hg/store/data/cglsup/_makefile.i | Bin 0 -> 828 bytes .../hg/.hg/store/data/cglsup/cglsup.go.i | Bin 0 -> 7333 bytes .../.hg/store/data/cglsup/cglsup__test.go.i | Bin 0 -> 3409 bytes .../hg/.hg/store/data/cgltim.go.i | Bin 0 -> 3639 bytes .../hg/.hg/store/data/cglutl/_makefile.i | Bin 0 -> 990 bytes .../hg/.hg/store/data/cglutl/cglutl.go.i | Bin 0 -> 3203 bytes .../.hg/store/data/cglutl/cglutl__test.go.i | Bin 0 -> 5796 bytes .../hg/.hg/store/data/cglutl/cglutlmrp.go.i | Bin 0 -> 3078 bytes .../hg/.hg/store/data/cglutl/cglutlrre.go.i | Bin 0 -> 1689 bytes .../hg/.hg/store/data/cglutl/cglutlsrt.go.i | Bin 0 -> 2269 bytes .../hg/.hg/store/data/cglutl/cglutlsup.go.i | Bin 0 -> 2038 bytes .../hg/.hg/store/data/cglutl/cglutltim.go.i | Bin 0 -> 2334 bytes .../hg/.hg/store/data/cglutl/cglutluid.go.i | Bin 0 -> 2883 bytes .../hg/.hg/store/fncache | 60 ++ .../hg/.hg/store/undo | Bin 0 -> 1573 bytes .../hg/.hg/tags.cache | 6 + .../hg/.hg/undo.branch | 1 + .../hg/.hg/undo.desc | 3 + .../hg/.hg/undo.dirstate | 0 .../tideland-cgl.googlecode.com/hg/.hgtags | 5 + .../hg/LICENSE.txt | 28 + .../tideland-cgl.googlecode.com/hg/Makefile | 31 + .../tideland-cgl.googlecode.com/hg/cgl.go | 288 ++++++ .../hg/cgl_test.go | 972 ++++++++++++++++++ .../tideland-cgl.googlecode.com/hg/cglfsm.go | 244 +++++ .../tideland-cgl.googlecode.com/hg/cglmon.go | 569 ++++++++++ .../tideland-cgl.googlecode.com/hg/cglsml.go | 490 +++++++++ .../tideland-cgl.googlecode.com/hg/cglsmr.go | 408 ++++++++ .../tideland-cgl.googlecode.com/hg/cglsup.go | 290 ++++++ .../tideland-cgl.googlecode.com/hg/cgltim.go | 316 ++++++ eBook/examples/chapter_11/type_interfaces.go | 62 ++ eBook/examples/chapter_12/cat.go | 36 + eBook/examples/chapter_12/cat2.go | 41 + eBook/examples/chapter_12/echo.go | 29 + eBook/examples/chapter_12/filecopy.go | 29 + eBook/examples/chapter_12/fileinput.go | 34 + eBook/examples/chapter_12/fileoutput.go | 28 + eBook/examples/chapter_12/filewrite.go | 10 + eBook/examples/chapter_12/gob1.go | 41 + eBook/examples/chapter_12/gob2.go | 39 + eBook/examples/chapter_12/gzipped.go | 35 + eBook/examples/chapter_12/hash_sha1.go | 31 + eBook/examples/chapter_12/input.dat | 5 + eBook/examples/chapter_12/io_interfaces.go | 18 + eBook/examples/chapter_12/json.go | 40 + eBook/examples/chapter_12/json_xml_case.go | 54 + eBook/examples/chapter_12/os_args.go | 16 + eBook/examples/chapter_12/output.dat | 10 + eBook/examples/chapter_12/products.txt | 3 + eBook/examples/chapter_12/products2.txt | 3 + eBook/examples/chapter_12/products_copy.txt | 3 + eBook/examples/chapter_12/read_file2.go | 38 + eBook/examples/chapter_12/read_files.go | 30 + eBook/examples/chapter_12/read_write_file1.go | 21 + eBook/examples/chapter_12/readinput1.go | 24 + eBook/examples/chapter_12/readinput2.go | 22 + eBook/examples/chapter_12/source.txt | 3 + eBook/examples/chapter_12/switch_input.go | 41 + eBook/examples/chapter_12/target.txt | 3 + eBook/examples/chapter_12/test | 1 + eBook/examples/chapter_12/vcard.gob | Bin 0 -> 228 bytes eBook/examples/chapter_12/vcard.json | 1 + eBook/examples/chapter_12/xml.go | 49 + eBook/examples/chapter_13/errors.go | 14 + eBook/examples/chapter_13/even/even/even.go | 10 + .../chapter_13/even/even/oddeven_test.go | 27 + .../chapter_13/even/even_main/even_main.go | 13 + eBook/examples/chapter_13/exec.go | 61 ++ eBook/examples/chapter_13/panic.go | 9 + eBook/examples/chapter_13/panic_package.go | 39 + eBook/examples/chapter_13/panic_recover.go | 32 + eBook/examples/chapter_13/parse/parse.go | 51 + eBook/examples/chapter_13/xtime | 2 + .../examples/chapter_14/benchmark_channels.go | 35 + eBook/examples/chapter_14/chaining.go | 23 + eBook/examples/chapter_14/channel_block.go | 16 + eBook/examples/chapter_14/channel_block2.go | 25 + eBook/examples/chapter_14/channel_idiom.go | 28 + eBook/examples/chapter_14/channel_idiom2.go | 29 + eBook/examples/chapter_14/conc_access.go | 54 + .../chapter_14/general_lazy_evalution1.go | 57 + eBook/examples/chapter_14/goroutine1.go | 29 + eBook/examples/chapter_14/goroutine2.go | 33 + eBook/examples/chapter_14/goroutine3.go | 29 + eBook/examples/chapter_14/goroutine_select.go | 40 + .../examples/chapter_14/goroutine_select2.go | 49 + eBook/examples/chapter_14/lazy_evaluation.go | 30 + eBook/examples/chapter_14/max_tasks.go | 31 + eBook/examples/chapter_14/multiplex_server.go | 53 + .../examples/chapter_14/multiplex_server2.go | 58 ++ eBook/examples/chapter_14/sieve1.go | 37 + eBook/examples/chapter_14/sieve2.go | 53 + eBook/examples/chapter_14/timer_goroutine.go | 42 + .../chapter_16/closures_goroutines.go | 47 + .../examples/chapter_16/pointer_interface.go | 31 + eBook/examples/chapter_19/goto_v1/Makefile | 13 + eBook/examples/chapter_19/goto_v1/key.go | 19 + eBook/examples/chapter_19/goto_v1/main.go | 41 + eBook/examples/chapter_19/goto_v1/store.go | 45 + eBook/examples/chapter_19/goto_v2/Makefile | 13 + eBook/examples/chapter_19/goto_v2/key.go | 19 + eBook/examples/chapter_19/goto_v2/main.go | 42 + eBook/examples/chapter_19/goto_v2/store.go | 90 ++ eBook/examples/chapter_19/goto_v2/store.gob | 0 eBook/examples/chapter_19/goto_v3/Makefile | 13 + eBook/examples/chapter_19/goto_v3/key.go | 19 + eBook/examples/chapter_19/goto_v3/main.go | 50 + eBook/examples/chapter_19/goto_v3/store.go | 111 ++ eBook/examples/chapter_19/goto_v3/store.gob | Bin 0 -> 155 bytes eBook/examples/chapter_19/goto_v4/Makefile | 13 + eBook/examples/chapter_19/goto_v4/key.go | 19 + eBook/examples/chapter_19/goto_v4/main.go | 50 + eBook/examples/chapter_19/goto_v4/store.go | 103 ++ eBook/examples/chapter_19/goto_v4/store.json | 4 + eBook/examples/chapter_19/goto_v5/Makefile | 13 + eBook/examples/chapter_19/goto_v5/demo.sh | 15 + eBook/examples/chapter_19/goto_v5/key.go | 19 + eBook/examples/chapter_19/goto_v5/main.go | 70 ++ eBook/examples/chapter_19/goto_v5/store.go | 147 +++ eBook/examples/chapter_19/goto_v5/store.gob | Bin 0 -> 375 bytes eBook/examples/chapter_2/hello_world1.go | 14 +- eBook/examples/chapter_2/version.go | 24 +- eBook/examples/chapter_20/helloapp/app.yaml | 8 + .../helloapp/hello/helloworld2_version1.go | 14 + .../helloapp/hello/helloworld2_version2.go | 28 + .../helloapp/hello/helloworld2_version3.go | 46 + .../helloapp/hello/helloworld2_version4.go | 72 ++ eBook/examples/chapter_20/helloworld.go | 16 + eBook/examples/chapter_3/CandGo/Makefile | 12 +- eBook/examples/chapter_3/CandGo/c1.go | 26 +- eBook/examples/chapter_3/CandGo/c2.go | 26 +- eBook/examples/chapter_3/Makefile | 14 +- eBook/examples/chapter_3/gocomp | 18 +- eBook/examples/chapter_3/gocomp.bat | 4 +- eBook/examples/chapter_3/run.cmd | 18 +- eBook/examples/chapter_4/alias.go | 14 +- eBook/examples/chapter_4/casting.go | 34 +- eBook/examples/chapter_4/char.go | 42 +- eBook/examples/chapter_4/count_substring.go | 34 +- .../chapter_4/function_calls_function.go | 28 +- eBook/examples/chapter_4/global_scope.go | 26 +- eBook/examples/chapter_4/goos.go | 50 +- eBook/examples/chapter_4/gotemplate.go | 60 +- eBook/examples/chapter_4/hello_world.go | 14 +- eBook/examples/chapter_4/hello_world2.go | 14 +- eBook/examples/chapter_4/index_in_string.go | 42 +- eBook/examples/chapter_4/init.go | 34 +- eBook/examples/chapter_4/local_scope.go | 22 +- eBook/examples/chapter_4/pointer.go | 24 +- eBook/examples/chapter_4/presuffix.go | 26 +- eBook/examples/chapter_4/random.go | 56 +- eBook/examples/chapter_4/repeat_string.go | 28 +- eBook/examples/chapter_4/string_conversion.go | 40 +- eBook/examples/chapter_4/string_pointer.go | 26 +- eBook/examples/chapter_4/strings_splitjoin.go | 64 +- eBook/examples/chapter_4/testcrash.go | 22 +- eBook/examples/chapter_4/time.go | 54 +- eBook/examples/chapter_4/toupper_lower.go | 36 +- eBook/examples/chapter_4/type.go | 20 +- eBook/examples/chapter_4/type_mixing.go | 16 +- eBook/examples/chapter_4/use_init.go | 24 +- eBook/examples/chapter_4/user_init.go | 16 +- eBook/examples/chapter_5/booleans.go | 24 +- eBook/examples/chapter_5/for1.go | 18 +- eBook/examples/chapter_5/for2.go | 24 +- eBook/examples/chapter_5/for3.go | 30 +- eBook/examples/chapter_5/for4.go | 24 +- eBook/examples/chapter_5/for5.go | 22 +- eBook/examples/chapter_5/for6.go | 34 +- eBook/examples/chapter_5/for_string.go | 112 +- eBook/examples/chapter_5/goto.go | 22 +- eBook/examples/chapter_5/goto2.go | 24 +- eBook/examples/chapter_5/ifelse.go | 44 +- eBook/examples/chapter_5/range_string.go | 160 +-- .../examples/chapter_5/string_conversion2.go | 50 +- eBook/examples/chapter_5/switch1.go | 32 +- eBook/examples/chapter_5/switch2.go | 32 +- eBook/examples/chapter_6/blank_identifier.go | 29 +- eBook/examples/chapter_6/defer.go | 17 + eBook/examples/chapter_6/defer_dbconn.go | 38 + eBook/examples/chapter_6/defer_logvalues.go | 19 + eBook/examples/chapter_6/defer_tracing.go | 22 + eBook/examples/chapter_6/defer_tracing2.go | 25 + eBook/examples/chapter_6/fibonacci.go | 56 + .../chapter_6/fibonacci_memoization.go | 42 + eBook/examples/chapter_6/filter_factory.go | 53 + eBook/examples/chapter_6/function_closure.go | 18 + eBook/examples/chapter_6/function_filter.go | 48 + eBook/examples/chapter_6/function_literal.go | 15 + .../examples/chapter_6/function_parameter.go | 20 + eBook/examples/chapter_6/function_return.go | 27 + eBook/examples/chapter_6/greeting.go | 22 +- eBook/examples/chapter_6/minmax.go | 38 +- eBook/examples/chapter_6/multiple_return.go | 56 +- eBook/examples/chapter_6/mut_recurs.go | 27 + eBook/examples/chapter_6/return_defer.go | 18 + eBook/examples/chapter_6/side_effect.go | 35 +- eBook/examples/chapter_6/simple_function.go | 30 +- eBook/examples/chapter_6/varnumpar.go | 28 + eBook/examples/chapter_7/array_literals.go | 38 +- eBook/examples/chapter_7/array_slices.go | 65 +- eBook/examples/chapter_7/array_sum.go | 33 +- eBook/examples/chapter_7/copy_append_slice.go | 31 +- eBook/examples/chapter_7/for_arrays.go | 30 +- eBook/examples/chapter_7/for_string.go | 11 + eBook/examples/chapter_7/make_slice.go | 35 +- eBook/examples/chapter_7/multidim_array.go | 51 +- eBook/examples/chapter_7/pointer_array.go | 22 +- eBook/examples/chapter_7/pointer_array2.go | 21 +- eBook/examples/chapter_7/reslicing.go | 35 +- eBook/examples/chapter_7/slices_forrange.go | 37 +- eBook/examples/chapter_7/slices_forrange2.go | 45 +- eBook/examples/chapter_8/Makefile.txt | 7 + eBook/examples/chapter_8/invert_map.go | 52 +- eBook/examples/chapter_8/make_maps.go | 33 +- eBook/examples/chapter_8/map_func.go | 24 +- eBook/examples/chapter_8/map_testelement.go | 64 +- eBook/examples/chapter_8/maps_forrange.go | 28 +- eBook/examples/chapter_8/slice_maps.go | 47 +- eBook/examples/chapter_8/sort_map.go | 75 +- eBook/examples/chapter_9/big.go | 30 + .../examples/chapter_9/book/book_main/main.go | 14 + eBook/examples/chapter_9/book/pack1/pack1.go | 8 + ...ge sort - The Go Programming Language.html | 152 +++ .../all.css | 205 ++++ .../godocs.js | 190 ++++ eBook/examples/chapter_9/doc_example/sort.go | 59 ++ .../chapter_9/doc_example/sortmain.go | 82 ++ eBook/examples/chapter_9/pattern.go | 35 + eBook/examples/chapter_9/reboot.go | 21 + eBook/examples/chapter_9/uppercase/uc/uc.go | 8 + .../chapter_9/uppercase/uc/uc_test.go | 23 + .../chapter_9/uppercase/uc_main/ucmain.go | 12 + eBook/examples/chapter_9/use_urlshortener.go | 55 + .../exercises/chapter_10/anonymous_struct.go | 15 + eBook/exercises/chapter_10/celsius.go | 19 + eBook/exercises/chapter_10/days.go | 36 + eBook/exercises/chapter_10/employee_salary.go | 25 + eBook/exercises/chapter_10/inherit_methods.go | 40 + eBook/exercises/chapter_10/inheritance_car.go | 59 ++ eBook/exercises/chapter_10/iteration_list.go | 23 + eBook/exercises/chapter_10/magic.go | 29 + eBook/exercises/chapter_10/main_stack.go | 45 + eBook/exercises/chapter_10/personex1.go | 40 + eBook/exercises/chapter_10/point.go | 49 + eBook/exercises/chapter_10/point_methods.go | 54 + eBook/exercises/chapter_10/rectangle.go | 28 + .../chapter_10/stack/stack_struct.go | 32 + eBook/exercises/chapter_10/stack_arr.go | 64 ++ eBook/exercises/chapter_10/stack_struct.go | 59 ++ eBook/exercises/chapter_10/timezones.go | 40 + eBook/exercises/chapter_10/type_string.go | 19 + eBook/exercises/chapter_10/vcard.go | 44 + eBook/exercises/chapter_11/float_sort.go | 66 ++ eBook/exercises/chapter_11/float_sortmain.go | 25 + eBook/exercises/chapter_11/interface_nil.go | 46 + eBook/exercises/chapter_11/interface_poly3.go | 68 ++ eBook/exercises/chapter_11/interfaces_ext.go | 51 + .../exercises/chapter_11/interfaces_poly2.go | 57 + eBook/exercises/chapter_11/main_stack.go | 29 + eBook/exercises/chapter_11/main_stack_v2.go | 17 + .../chapter_11/map_function_interface.go | 62 ++ .../chapter_11/map_function_interface_var.go | 59 ++ eBook/exercises/chapter_11/min_interface.go | 28 + eBook/exercises/chapter_11/minmain.go | 31 + .../exercises/chapter_11/point_interfaces.go | 89 ++ eBook/exercises/chapter_11/print.go | 43 + .../exercises/chapter_11/simple_interface.go | 34 + .../exercises/chapter_11/simple_interface2.go | 61 ++ .../exercises/chapter_11/simple_interface3.go | 74 ++ eBook/exercises/chapter_11/sort/sort.go | 60 ++ eBook/exercises/chapter_11/sort_persons.go | 36 + .../chapter_11/stack/stack_general.go | 39 + .../chapter_11/stack/stack_general_v2.go | 28 + eBook/exercises/chapter_12/calculator.go | 53 + eBook/exercises/chapter_12/cat_numbered.go | 43 + eBook/exercises/chapter_12/degob.go | 41 + eBook/exercises/chapter_12/goprogram | 10 + eBook/exercises/chapter_12/goprogramT | Bin 0 -> 50 bytes eBook/exercises/chapter_12/hash_md5.go | 20 + eBook/exercises/chapter_12/hello_who.go | 16 + eBook/exercises/chapter_12/products.txt | 4 + eBook/exercises/chapter_12/read_csv.go | 67 ++ .../exercises/chapter_12/remove_3till5char.go | 37 + .../chapter_12/stack/stack_struct.go | 32 + eBook/exercises/chapter_12/test | 3 + eBook/exercises/chapter_12/vcard.gob | Bin 0 -> 228 bytes .../exercises/chapter_12/word_letter_count.go | 37 + eBook/exercises/chapter_13/Makefile | 6 + eBook/exercises/chapter_13/panic_defer.go | 44 + .../chapter_13/panic_defer_convint.go | 44 + .../exercises/chapter_13/recover_divbyzero.go | 34 + eBook/exercises/chapter_13/string_reverse.go | 18 + .../chapter_13/string_reverse_test.go | 40 + eBook/exercises/chapter_14/blocking.go | 19 + eBook/exercises/chapter_14/channel_block3.go | 22 + eBook/exercises/chapter_14/channel_buffer.go | 21 + eBook/exercises/chapter_14/concurrent_pi.go | 45 + eBook/exercises/chapter_14/concurrent_pi2.go | 45 + .../chapter_14/general_lazy_evalution2.go | 59 ++ eBook/exercises/chapter_14/gofibonacci.go | 44 + eBook/exercises/chapter_14/gofibonacci2.go | 35 + eBook/exercises/chapter_14/gofibonacci3.go | 45 + .../chapter_14/gofibonacci_select.go | 42 + eBook/exercises/chapter_14/goroutine_close.go | 26 + eBook/exercises/chapter_14/goroutine_panic.go | 22 + .../exercises/chapter_14/goroutine_select.go | 31 + eBook/exercises/chapter_14/gosum.go | 16 + .../exercises/chapter_14/multiplex_server3.go | 58 ++ .../chapter_14/polar_to_cartesian.go | 101 ++ .../exercises/chapter_14/producer_consumer.go | 42 + .../chapter_14/producer_consumer2.go | 29 + eBook/exercises/chapter_14/random_bitgen.go | 23 + eBook/exercises/chapter_15/client1.go | 46 + eBook/exercises/chapter_15/hello_server.go | 19 + eBook/exercises/chapter_15/http_fetch2.go | 31 + eBook/exercises/chapter_15/server1.go | 75 ++ eBook/exercises/chapter_15/statistics.go | 104 ++ .../chapter_15/template_validation_recover.go | 29 + .../chapter_15/twitter_status_json.go | 33 + eBook/exercises/chapter_15/webhello2.go | 24 + eBook/exercises/chapter_4/count_characters.go | 42 +- eBook/exercises/chapter_4/divby0.go | 16 +- .../chapter_4/function_calls_function.go | 34 +- eBook/exercises/chapter_4/global_scope.go | 36 +- eBook/exercises/chapter_4/local_scope.go | 32 +- .../exercises/chapter_5/bitwise_complement.go | 42 +- eBook/exercises/chapter_5/fizzbuzz.go | 46 +- eBook/exercises/chapter_5/for_character.go | 32 +- eBook/exercises/chapter_5/for_loop.go | 30 +- eBook/exercises/chapter_5/i_undefined.go | 28 +- eBook/exercises/chapter_5/multiple_for.go | 32 +- eBook/exercises/chapter_5/rectangle_stars.go | 52 +- eBook/exercises/chapter_5/season.go | 32 +- eBook/exercises/chapter_6/10to1_recursive.go | 13 + eBook/exercises/chapter_6/compose.go | 17 + eBook/exercises/chapter_6/error_returnval.go | 99 +- eBook/exercises/chapter_6/factorial.go | 34 + eBook/exercises/chapter_6/fibonacci2.go | 24 + .../exercises/chapter_6/fibonacci_closure.go | 20 + eBook/exercises/chapter_6/function_filter2.go | 37 + eBook/exercises/chapter_6/lambda_value.go | 18 + eBook/exercises/chapter_6/mult_returnval.go | 51 +- eBook/exercises/chapter_6/strings_map.go | 13 + eBook/exercises/chapter_6/varargs.go | 23 + eBook/exercises/chapter_7/array_value.go | 22 + eBook/exercises/chapter_7/bubblesort.go | 27 + eBook/exercises/chapter_7/fibonacci_array.go | 18 + .../chapter_7/fibonacci_funcarray.go | 22 + eBook/exercises/chapter_7/filter_slice.go | 32 + eBook/exercises/chapter_7/for_array.go | 13 + eBook/exercises/chapter_7/insert_slice.go | 23 + eBook/exercises/chapter_7/magnify_slice.go | 25 + eBook/exercises/chapter_7/map_function.go | 32 + eBook/exercises/chapter_7/min_max.go | 39 + eBook/exercises/chapter_7/remove_slice.go | 19 + eBook/exercises/chapter_7/split_string.go | 16 + eBook/exercises/chapter_7/string_reverse.go | 41 + eBook/exercises/chapter_7/string_split2.go | 15 + eBook/exercises/chapter_7/sum_array.go | 39 + eBook/exercises/chapter_7/uniq.go | 23 + eBook/exercises/chapter_8/map_days.go | 35 + eBook/exercises/chapter_8/map_drinks.go | 73 ++ eBook/exercises/chapter_9/dlinked_list.go | 28 + eBook/exercises/chapter_9/even/even.go | 6 + eBook/exercises/chapter_9/fibo/fibonacci.go | 33 + .../chapter_9/greetings/greetings.go | 27 + eBook/exercises/chapter_9/main_fibo.go | 62 ++ eBook/exercises/chapter_9/main_greetings.go | 22 + eBook/exercises/chapter_9/main_oddeven.go | 13 + eBook/exercises/chapter_9/size_int.go | 14 + 465 files changed, 15392 insertions(+), 1572 deletions(-) create mode 100644 eBook/examples/chapter_10/embed_func1.go create mode 100644 eBook/examples/chapter_10/embed_func2.go create mode 100644 eBook/examples/chapter_10/embedd_struct.go create mode 100644 eBook/examples/chapter_10/main.go create mode 100644 eBook/examples/chapter_10/method1.go create mode 100644 eBook/examples/chapter_10/method2.go create mode 100644 eBook/examples/chapter_10/method3.go create mode 100644 eBook/examples/chapter_10/method4.go create mode 100644 eBook/examples/chapter_10/method_on_time.go create mode 100644 eBook/examples/chapter_10/method_string.go create mode 100644 eBook/examples/chapter_10/methodset1.go create mode 100644 eBook/examples/chapter_10/mult_inheritance.go create mode 100644 eBook/examples/chapter_10/new_make.go create mode 100644 eBook/examples/chapter_10/person.go create mode 100644 eBook/examples/chapter_10/person2.go create mode 100644 eBook/examples/chapter_10/pointer_value.go create mode 100644 eBook/examples/chapter_10/struct_conversions.go create mode 100644 eBook/examples/chapter_10/struct_pack/structPack.go create mode 100644 eBook/examples/chapter_10/struct_tag.go create mode 100644 eBook/examples/chapter_10/structs_anonymous_fields.go create mode 100644 eBook/examples/chapter_10/structs_fields.go create mode 100644 eBook/examples/chapter_10/use_person2.go create mode 100644 eBook/examples/chapter_10/vcard.json create mode 100644 eBook/examples/chapter_11/cars.go create mode 100644 eBook/examples/chapter_11/duck_dance.go create mode 100644 eBook/examples/chapter_11/empty_interface.go create mode 100644 eBook/examples/chapter_11/emptyint_switch.go create mode 100644 eBook/examples/chapter_11/interfaces.go create mode 100644 eBook/examples/chapter_11/interfaces_poly.go create mode 100644 eBook/examples/chapter_11/methodset2.go create mode 100644 eBook/examples/chapter_11/multi_interfaces_poly.go create mode 100644 eBook/examples/chapter_11/node_structures.go create mode 100644 eBook/examples/chapter_11/print.go create mode 100644 eBook/examples/chapter_11/reflect1.go create mode 100644 eBook/examples/chapter_11/reflect2.go create mode 100644 eBook/examples/chapter_11/reflect_struct.go create mode 100644 eBook/examples/chapter_11/reflect_struct2.go create mode 100644 eBook/examples/chapter_11/sort/sort.go create mode 100644 eBook/examples/chapter_11/sortmain.go create mode 100644 eBook/examples/chapter_11/static.go create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/00changelog.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/branch create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/branchheads.cache create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/dirstate create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/hgrc create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/requires create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00changelog.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00manifest.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_l_i_c_e_n_s_e.txt.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgldoc/_l_i_c_e_n_s_e.txt.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecaucb.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecauep.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecautl.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonetm.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonssi.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmrp.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnum.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnum__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumgra.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumsta.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredcmd.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredres.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredurp.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsml.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsml__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/cglsmlpap.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsmr.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsrt.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgltim.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/_makefile.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl__test.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlmrp.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlrre.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlsrt.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlsup.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutltim.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutluid.go.i create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/fncache create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/undo create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/tags.cache create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.branch create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.desc create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.dirstate create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hgtags create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/LICENSE.txt create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/Makefile create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl.go create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl_test.go create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglfsm.go create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglmon.go create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsml.go create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsmr.go create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsup.go create mode 100644 eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgltim.go create mode 100644 eBook/examples/chapter_11/type_interfaces.go create mode 100644 eBook/examples/chapter_12/cat.go create mode 100644 eBook/examples/chapter_12/cat2.go create mode 100644 eBook/examples/chapter_12/echo.go create mode 100644 eBook/examples/chapter_12/filecopy.go create mode 100644 eBook/examples/chapter_12/fileinput.go create mode 100644 eBook/examples/chapter_12/fileoutput.go create mode 100644 eBook/examples/chapter_12/filewrite.go create mode 100644 eBook/examples/chapter_12/gob1.go create mode 100644 eBook/examples/chapter_12/gob2.go create mode 100644 eBook/examples/chapter_12/gzipped.go create mode 100644 eBook/examples/chapter_12/hash_sha1.go create mode 100644 eBook/examples/chapter_12/input.dat create mode 100644 eBook/examples/chapter_12/io_interfaces.go create mode 100644 eBook/examples/chapter_12/json.go create mode 100644 eBook/examples/chapter_12/json_xml_case.go create mode 100644 eBook/examples/chapter_12/os_args.go create mode 100644 eBook/examples/chapter_12/output.dat create mode 100644 eBook/examples/chapter_12/products.txt create mode 100644 eBook/examples/chapter_12/products2.txt create mode 100644 eBook/examples/chapter_12/products_copy.txt create mode 100644 eBook/examples/chapter_12/read_file2.go create mode 100644 eBook/examples/chapter_12/read_files.go create mode 100644 eBook/examples/chapter_12/read_write_file1.go create mode 100644 eBook/examples/chapter_12/readinput1.go create mode 100644 eBook/examples/chapter_12/readinput2.go create mode 100644 eBook/examples/chapter_12/source.txt create mode 100644 eBook/examples/chapter_12/switch_input.go create mode 100644 eBook/examples/chapter_12/target.txt create mode 100644 eBook/examples/chapter_12/test create mode 100644 eBook/examples/chapter_12/vcard.gob create mode 100644 eBook/examples/chapter_12/vcard.json create mode 100644 eBook/examples/chapter_12/xml.go create mode 100644 eBook/examples/chapter_13/errors.go create mode 100644 eBook/examples/chapter_13/even/even/even.go create mode 100644 eBook/examples/chapter_13/even/even/oddeven_test.go create mode 100644 eBook/examples/chapter_13/even/even_main/even_main.go create mode 100644 eBook/examples/chapter_13/exec.go create mode 100644 eBook/examples/chapter_13/panic.go create mode 100644 eBook/examples/chapter_13/panic_package.go create mode 100644 eBook/examples/chapter_13/panic_recover.go create mode 100644 eBook/examples/chapter_13/parse/parse.go create mode 100644 eBook/examples/chapter_13/xtime create mode 100644 eBook/examples/chapter_14/benchmark_channels.go create mode 100644 eBook/examples/chapter_14/chaining.go create mode 100644 eBook/examples/chapter_14/channel_block.go create mode 100644 eBook/examples/chapter_14/channel_block2.go create mode 100644 eBook/examples/chapter_14/channel_idiom.go create mode 100644 eBook/examples/chapter_14/channel_idiom2.go create mode 100644 eBook/examples/chapter_14/conc_access.go create mode 100644 eBook/examples/chapter_14/general_lazy_evalution1.go create mode 100644 eBook/examples/chapter_14/goroutine1.go create mode 100644 eBook/examples/chapter_14/goroutine2.go create mode 100644 eBook/examples/chapter_14/goroutine3.go create mode 100644 eBook/examples/chapter_14/goroutine_select.go create mode 100644 eBook/examples/chapter_14/goroutine_select2.go create mode 100644 eBook/examples/chapter_14/lazy_evaluation.go create mode 100644 eBook/examples/chapter_14/max_tasks.go create mode 100644 eBook/examples/chapter_14/multiplex_server.go create mode 100644 eBook/examples/chapter_14/multiplex_server2.go create mode 100644 eBook/examples/chapter_14/sieve1.go create mode 100644 eBook/examples/chapter_14/sieve2.go create mode 100644 eBook/examples/chapter_14/timer_goroutine.go create mode 100644 eBook/examples/chapter_16/closures_goroutines.go create mode 100644 eBook/examples/chapter_16/pointer_interface.go create mode 100644 eBook/examples/chapter_19/goto_v1/Makefile create mode 100644 eBook/examples/chapter_19/goto_v1/key.go create mode 100644 eBook/examples/chapter_19/goto_v1/main.go create mode 100644 eBook/examples/chapter_19/goto_v1/store.go create mode 100644 eBook/examples/chapter_19/goto_v2/Makefile create mode 100644 eBook/examples/chapter_19/goto_v2/key.go create mode 100644 eBook/examples/chapter_19/goto_v2/main.go create mode 100644 eBook/examples/chapter_19/goto_v2/store.go create mode 100644 eBook/examples/chapter_19/goto_v2/store.gob create mode 100644 eBook/examples/chapter_19/goto_v3/Makefile create mode 100644 eBook/examples/chapter_19/goto_v3/key.go create mode 100644 eBook/examples/chapter_19/goto_v3/main.go create mode 100644 eBook/examples/chapter_19/goto_v3/store.go create mode 100644 eBook/examples/chapter_19/goto_v3/store.gob create mode 100644 eBook/examples/chapter_19/goto_v4/Makefile create mode 100644 eBook/examples/chapter_19/goto_v4/key.go create mode 100644 eBook/examples/chapter_19/goto_v4/main.go create mode 100644 eBook/examples/chapter_19/goto_v4/store.go create mode 100644 eBook/examples/chapter_19/goto_v4/store.json create mode 100644 eBook/examples/chapter_19/goto_v5/Makefile create mode 100644 eBook/examples/chapter_19/goto_v5/demo.sh create mode 100644 eBook/examples/chapter_19/goto_v5/key.go create mode 100644 eBook/examples/chapter_19/goto_v5/main.go create mode 100644 eBook/examples/chapter_19/goto_v5/store.go create mode 100644 eBook/examples/chapter_19/goto_v5/store.gob create mode 100644 eBook/examples/chapter_20/helloapp/app.yaml create mode 100644 eBook/examples/chapter_20/helloapp/hello/helloworld2_version1.go create mode 100644 eBook/examples/chapter_20/helloapp/hello/helloworld2_version2.go create mode 100644 eBook/examples/chapter_20/helloapp/hello/helloworld2_version3.go create mode 100644 eBook/examples/chapter_20/helloapp/hello/helloworld2_version4.go create mode 100644 eBook/examples/chapter_20/helloworld.go create mode 100644 eBook/examples/chapter_6/defer.go create mode 100644 eBook/examples/chapter_6/defer_dbconn.go create mode 100644 eBook/examples/chapter_6/defer_logvalues.go create mode 100644 eBook/examples/chapter_6/defer_tracing.go create mode 100644 eBook/examples/chapter_6/defer_tracing2.go create mode 100644 eBook/examples/chapter_6/fibonacci.go create mode 100644 eBook/examples/chapter_6/fibonacci_memoization.go create mode 100644 eBook/examples/chapter_6/filter_factory.go create mode 100644 eBook/examples/chapter_6/function_closure.go create mode 100644 eBook/examples/chapter_6/function_filter.go create mode 100644 eBook/examples/chapter_6/function_literal.go create mode 100644 eBook/examples/chapter_6/function_parameter.go create mode 100644 eBook/examples/chapter_6/function_return.go create mode 100644 eBook/examples/chapter_6/mut_recurs.go create mode 100644 eBook/examples/chapter_6/return_defer.go create mode 100644 eBook/examples/chapter_6/varnumpar.go create mode 100644 eBook/examples/chapter_7/for_string.go create mode 100644 eBook/examples/chapter_8/Makefile.txt create mode 100644 eBook/examples/chapter_9/big.go create mode 100644 eBook/examples/chapter_9/book/book_main/main.go create mode 100644 eBook/examples/chapter_9/book/pack1/pack1.go create mode 100644 eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language.html create mode 100644 eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/all.css create mode 100644 eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/godocs.js create mode 100644 eBook/examples/chapter_9/doc_example/sort.go create mode 100644 eBook/examples/chapter_9/doc_example/sortmain.go create mode 100644 eBook/examples/chapter_9/pattern.go create mode 100644 eBook/examples/chapter_9/reboot.go create mode 100644 eBook/examples/chapter_9/uppercase/uc/uc.go create mode 100644 eBook/examples/chapter_9/uppercase/uc/uc_test.go create mode 100644 eBook/examples/chapter_9/uppercase/uc_main/ucmain.go create mode 100644 eBook/examples/chapter_9/use_urlshortener.go create mode 100755 eBook/exercises/chapter_10/anonymous_struct.go create mode 100755 eBook/exercises/chapter_10/celsius.go create mode 100755 eBook/exercises/chapter_10/days.go create mode 100755 eBook/exercises/chapter_10/employee_salary.go create mode 100755 eBook/exercises/chapter_10/inherit_methods.go create mode 100755 eBook/exercises/chapter_10/inheritance_car.go create mode 100755 eBook/exercises/chapter_10/iteration_list.go create mode 100755 eBook/exercises/chapter_10/magic.go create mode 100755 eBook/exercises/chapter_10/main_stack.go create mode 100755 eBook/exercises/chapter_10/personex1.go create mode 100755 eBook/exercises/chapter_10/point.go create mode 100755 eBook/exercises/chapter_10/point_methods.go create mode 100755 eBook/exercises/chapter_10/rectangle.go create mode 100755 eBook/exercises/chapter_10/stack/stack_struct.go create mode 100755 eBook/exercises/chapter_10/stack_arr.go create mode 100755 eBook/exercises/chapter_10/stack_struct.go create mode 100755 eBook/exercises/chapter_10/timezones.go create mode 100755 eBook/exercises/chapter_10/type_string.go create mode 100755 eBook/exercises/chapter_10/vcard.go create mode 100755 eBook/exercises/chapter_11/float_sort.go create mode 100755 eBook/exercises/chapter_11/float_sortmain.go create mode 100755 eBook/exercises/chapter_11/interface_nil.go create mode 100755 eBook/exercises/chapter_11/interface_poly3.go create mode 100755 eBook/exercises/chapter_11/interfaces_ext.go create mode 100755 eBook/exercises/chapter_11/interfaces_poly2.go create mode 100755 eBook/exercises/chapter_11/main_stack.go create mode 100755 eBook/exercises/chapter_11/main_stack_v2.go create mode 100755 eBook/exercises/chapter_11/map_function_interface.go create mode 100755 eBook/exercises/chapter_11/map_function_interface_var.go create mode 100755 eBook/exercises/chapter_11/min_interface.go create mode 100755 eBook/exercises/chapter_11/minmain.go create mode 100755 eBook/exercises/chapter_11/point_interfaces.go create mode 100755 eBook/exercises/chapter_11/print.go create mode 100755 eBook/exercises/chapter_11/simple_interface.go create mode 100755 eBook/exercises/chapter_11/simple_interface2.go create mode 100755 eBook/exercises/chapter_11/simple_interface3.go create mode 100755 eBook/exercises/chapter_11/sort/sort.go create mode 100755 eBook/exercises/chapter_11/sort_persons.go create mode 100755 eBook/exercises/chapter_11/stack/stack_general.go create mode 100755 eBook/exercises/chapter_11/stack/stack_general_v2.go create mode 100755 eBook/exercises/chapter_12/calculator.go create mode 100755 eBook/exercises/chapter_12/cat_numbered.go create mode 100755 eBook/exercises/chapter_12/degob.go create mode 100755 eBook/exercises/chapter_12/goprogram create mode 100755 eBook/exercises/chapter_12/goprogramT create mode 100755 eBook/exercises/chapter_12/hash_md5.go create mode 100755 eBook/exercises/chapter_12/hello_who.go create mode 100755 eBook/exercises/chapter_12/products.txt create mode 100755 eBook/exercises/chapter_12/read_csv.go create mode 100755 eBook/exercises/chapter_12/remove_3till5char.go create mode 100755 eBook/exercises/chapter_12/stack/stack_struct.go create mode 100755 eBook/exercises/chapter_12/test create mode 100755 eBook/exercises/chapter_12/vcard.gob create mode 100755 eBook/exercises/chapter_12/word_letter_count.go create mode 100755 eBook/exercises/chapter_13/Makefile create mode 100755 eBook/exercises/chapter_13/panic_defer.go create mode 100755 eBook/exercises/chapter_13/panic_defer_convint.go create mode 100755 eBook/exercises/chapter_13/recover_divbyzero.go create mode 100755 eBook/exercises/chapter_13/string_reverse.go create mode 100755 eBook/exercises/chapter_13/string_reverse_test.go create mode 100755 eBook/exercises/chapter_14/blocking.go create mode 100755 eBook/exercises/chapter_14/channel_block3.go create mode 100755 eBook/exercises/chapter_14/channel_buffer.go create mode 100755 eBook/exercises/chapter_14/concurrent_pi.go create mode 100755 eBook/exercises/chapter_14/concurrent_pi2.go create mode 100755 eBook/exercises/chapter_14/general_lazy_evalution2.go create mode 100755 eBook/exercises/chapter_14/gofibonacci.go create mode 100755 eBook/exercises/chapter_14/gofibonacci2.go create mode 100755 eBook/exercises/chapter_14/gofibonacci3.go create mode 100755 eBook/exercises/chapter_14/gofibonacci_select.go create mode 100755 eBook/exercises/chapter_14/goroutine_close.go create mode 100755 eBook/exercises/chapter_14/goroutine_panic.go create mode 100755 eBook/exercises/chapter_14/goroutine_select.go create mode 100755 eBook/exercises/chapter_14/gosum.go create mode 100755 eBook/exercises/chapter_14/multiplex_server3.go create mode 100755 eBook/exercises/chapter_14/polar_to_cartesian.go create mode 100755 eBook/exercises/chapter_14/producer_consumer.go create mode 100755 eBook/exercises/chapter_14/producer_consumer2.go create mode 100755 eBook/exercises/chapter_14/random_bitgen.go create mode 100755 eBook/exercises/chapter_15/client1.go create mode 100755 eBook/exercises/chapter_15/hello_server.go create mode 100755 eBook/exercises/chapter_15/http_fetch2.go create mode 100755 eBook/exercises/chapter_15/server1.go create mode 100755 eBook/exercises/chapter_15/statistics.go create mode 100755 eBook/exercises/chapter_15/template_validation_recover.go create mode 100755 eBook/exercises/chapter_15/twitter_status_json.go create mode 100755 eBook/exercises/chapter_15/webhello2.go mode change 100644 => 100755 eBook/exercises/chapter_4/count_characters.go mode change 100644 => 100755 eBook/exercises/chapter_4/divby0.go mode change 100644 => 100755 eBook/exercises/chapter_4/function_calls_function.go mode change 100644 => 100755 eBook/exercises/chapter_4/global_scope.go mode change 100644 => 100755 eBook/exercises/chapter_4/local_scope.go mode change 100644 => 100755 eBook/exercises/chapter_5/bitwise_complement.go mode change 100644 => 100755 eBook/exercises/chapter_5/fizzbuzz.go mode change 100644 => 100755 eBook/exercises/chapter_5/for_character.go mode change 100644 => 100755 eBook/exercises/chapter_5/for_loop.go mode change 100644 => 100755 eBook/exercises/chapter_5/i_undefined.go mode change 100644 => 100755 eBook/exercises/chapter_5/multiple_for.go mode change 100644 => 100755 eBook/exercises/chapter_5/rectangle_stars.go mode change 100644 => 100755 eBook/exercises/chapter_5/season.go create mode 100755 eBook/exercises/chapter_6/10to1_recursive.go create mode 100755 eBook/exercises/chapter_6/compose.go mode change 100644 => 100755 eBook/exercises/chapter_6/error_returnval.go create mode 100755 eBook/exercises/chapter_6/factorial.go create mode 100755 eBook/exercises/chapter_6/fibonacci2.go create mode 100755 eBook/exercises/chapter_6/fibonacci_closure.go create mode 100755 eBook/exercises/chapter_6/function_filter2.go create mode 100755 eBook/exercises/chapter_6/lambda_value.go mode change 100644 => 100755 eBook/exercises/chapter_6/mult_returnval.go create mode 100755 eBook/exercises/chapter_6/strings_map.go create mode 100755 eBook/exercises/chapter_6/varargs.go create mode 100755 eBook/exercises/chapter_7/array_value.go create mode 100755 eBook/exercises/chapter_7/bubblesort.go create mode 100755 eBook/exercises/chapter_7/fibonacci_array.go create mode 100755 eBook/exercises/chapter_7/fibonacci_funcarray.go create mode 100755 eBook/exercises/chapter_7/filter_slice.go create mode 100755 eBook/exercises/chapter_7/for_array.go create mode 100755 eBook/exercises/chapter_7/insert_slice.go create mode 100755 eBook/exercises/chapter_7/magnify_slice.go create mode 100755 eBook/exercises/chapter_7/map_function.go create mode 100755 eBook/exercises/chapter_7/min_max.go create mode 100755 eBook/exercises/chapter_7/remove_slice.go create mode 100755 eBook/exercises/chapter_7/split_string.go create mode 100755 eBook/exercises/chapter_7/string_reverse.go create mode 100755 eBook/exercises/chapter_7/string_split2.go create mode 100755 eBook/exercises/chapter_7/sum_array.go create mode 100755 eBook/exercises/chapter_7/uniq.go create mode 100755 eBook/exercises/chapter_8/map_days.go create mode 100755 eBook/exercises/chapter_8/map_drinks.go create mode 100755 eBook/exercises/chapter_9/dlinked_list.go create mode 100755 eBook/exercises/chapter_9/even/even.go create mode 100755 eBook/exercises/chapter_9/fibo/fibonacci.go create mode 100755 eBook/exercises/chapter_9/greetings/greetings.go create mode 100755 eBook/exercises/chapter_9/main_fibo.go create mode 100755 eBook/exercises/chapter_9/main_greetings.go create mode 100755 eBook/exercises/chapter_9/main_oddeven.go create mode 100755 eBook/exercises/chapter_9/size_int.go diff --git a/eBook/examples/chapter_10/embed_func1.go b/eBook/examples/chapter_10/embed_func1.go new file mode 100644 index 0000000..ed92f27 --- /dev/null +++ b/eBook/examples/chapter_10/embed_func1.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" +) + +type Log struct { + msg string +} + +type Customer struct { + Name string + log *Log +} + +func main() { + // c := new(Customer) + // c.Name = "Barak Obama" + // c.log = new(Log) + // c.log.msg = "1 - Yes we can!" + // shorter: + c := &Customer{"Barak Obama", &Log{"1 - Yes we can!"}} + // fmt.Println(c) // &{Barak Obama 1 - Yes we can!} + c.Log().Add("2 - After me the world will be a better place!") + //fmt.Println(c.log) + fmt.Println(c.Log()) +} + +func (l *Log) Add(s string) { + l.msg += "\n" + s +} + +func (l *Log) String() string { + return l.msg +} + +func (c *Customer) Log() *Log { + return c.log +} +/* Output: +1 - Yes we can! +2 - After me the world will be a better place! +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/embed_func2.go b/eBook/examples/chapter_10/embed_func2.go new file mode 100644 index 0000000..f26b7e4 --- /dev/null +++ b/eBook/examples/chapter_10/embed_func2.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" +) + +type Log struct { + msg string +} + +type Customer struct { + Name string + Log +} + +func main() { + c := &Customer{"Barak Obama", Log{"1 - Yes we can!"}} + c.Add("2 - After me the world will be a better place!") + fmt.Println(c) +} + +func (l *Log) Add(s string) { + l.msg += "\n" + s +} + +func (c *Customer) String() string { + return c.Name + "\nLog:" + fmt.Sprintln(c.Log) +} + +func (l *Log) String() string { + return l.msg +} + +/* Output: +Barak Obama +Log:{1 - Yes we can! +2 - After me the world will be a better place!} +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/embedd_struct.go b/eBook/examples/chapter_10/embedd_struct.go new file mode 100644 index 0000000..bb24088 --- /dev/null +++ b/eBook/examples/chapter_10/embedd_struct.go @@ -0,0 +1,18 @@ +package main + +import "fmt" + +type A struct { + ax, ay int +} + +type B struct { + A + bx, by float32 +} + +func main() { + b := B{A{1, 2}, 3.0, 4.0} + fmt.Println(b.ax, b.ay, b.bx, b.by) + fmt.Println(b.A) +} diff --git a/eBook/examples/chapter_10/main.go b/eBook/examples/chapter_10/main.go new file mode 100644 index 0000000..8fecd16 --- /dev/null +++ b/eBook/examples/chapter_10/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + "./struct_pack/structPack" +) + +func main() { + struct1 := new(structPack.ExpStruct) + struct1.Mi1 = 10 + struct1.Mf1 = 16. + fmt.Printf("Mi1 = %d\n", struct1.Mi1) + fmt.Printf("Mf1 = %f\n", struct1.Mf1) +} +// Mi1 = 10 +// Mf1 = 16.000000 \ No newline at end of file diff --git a/eBook/examples/chapter_10/method1.go b/eBook/examples/chapter_10/method1.go new file mode 100644 index 0000000..35280f0 --- /dev/null +++ b/eBook/examples/chapter_10/method1.go @@ -0,0 +1,29 @@ +package main + +import "fmt" + +type TwoInts struct { + a int + b int +} + +func main() { + two1 := new(TwoInts) + two1.a = 12 + two1.b = 10 + + fmt.Printf("The sum is: %d\n", two1.AddThem()) + fmt.Printf("Add them to the param: %d\n", two1.AddToParam(20)) + + // literal: + two2 := TwoInts{3, 4} + fmt.Printf("The sum is: %d\n", two2.AddThem()) +} + +func (tn *TwoInts) AddThem() int { + return tn.a + tn.b +} + +func (tn *TwoInts) AddToParam(param int) int { + return tn.a + tn.b + param +} diff --git a/eBook/examples/chapter_10/method2.go b/eBook/examples/chapter_10/method2.go new file mode 100644 index 0000000..f6fc530 --- /dev/null +++ b/eBook/examples/chapter_10/method2.go @@ -0,0 +1,16 @@ +package main + +import "fmt" + +type IntVector []int + +func (v IntVector) Sum() (s int) { + for _, x := range v { + s += x + } + return +} + +func main() { + fmt.Println(IntVector{1, 2, 3}.Sum()) // Output: 6 +} diff --git a/eBook/examples/chapter_10/method3.go b/eBook/examples/chapter_10/method3.go new file mode 100644 index 0000000..a5b11d6 --- /dev/null +++ b/eBook/examples/chapter_10/method3.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "math" +) + +type Point struct { + x, y float64 +} + +func (p *Point) Abs() float64 { + return math.Sqrt(p.x*p.x + p.y*p.y) +} + +type NamedPoint struct { + Point + name string +} + +func main() { + n := &NamedPoint{Point{3, 4}, "Pythagoras"} + fmt.Println(n.Abs()) // prints 5 +} diff --git a/eBook/examples/chapter_10/method4.go b/eBook/examples/chapter_10/method4.go new file mode 100644 index 0000000..7d8b55a --- /dev/null +++ b/eBook/examples/chapter_10/method4.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + "math" +) + +type Point struct { + x, y float64 +} + +func (p *Point) Abs() float64 { + return math.Sqrt(p.x*p.x + p.y*p.y) +} + +type NamedPoint struct { + Point + name string +} + +func (n *NamedPoint) Abs() float64 { + return n.Point.Abs() * 100. +} + +func main() { + n := &NamedPoint{Point{3, 4}, "Pythagoras"} + fmt.Println(n.Abs()) // prints 500 +} diff --git a/eBook/examples/chapter_10/method_on_time.go b/eBook/examples/chapter_10/method_on_time.go new file mode 100644 index 0000000..ee422ae --- /dev/null +++ b/eBook/examples/chapter_10/method_on_time.go @@ -0,0 +1,25 @@ +// method_on_time.go +package main + +import ( + "fmt" + "time" +) + +type myTime struct { + time.Time //anonymous field +} + +func (t myTime) first3Chars() string { + return t.Time.String()[0:3] +} + +func main() { + m := myTime{time.Now()} + fmt.Println("Full time now:", m.String()) //calling existing String method on anonymous Time field + fmt.Println("First 3 chars:", m.first3Chars()) //calling myTime.first3Chars +} +/* Output: +Full time now: Mon Oct 24 15:34:54 Romance Daylight Time 2011 +First 3 chars: Mon +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/method_string.go b/eBook/examples/chapter_10/method_string.go new file mode 100644 index 0000000..0213139 --- /dev/null +++ b/eBook/examples/chapter_10/method_string.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "strconv" +) + +type TwoInts struct { + a int + b int +} + +func main() { + two1 := new(TwoInts) + two1.a = 12 + two1.b = 10 + fmt.Printf("two1 is: %v\n", two1) + fmt.Println("two1 is:", two1) + fmt.Printf("two1 is: %T\n", two1) + fmt.Printf("two1 is: %#v\n", two1) +} + +func (tn *TwoInts) String() string { + return "(" + strconv.Itoa(tn.a) + " / " + strconv.Itoa(tn.b) + ")" +} + + diff --git a/eBook/examples/chapter_10/methodset1.go b/eBook/examples/chapter_10/methodset1.go new file mode 100644 index 0000000..c8d8c6d --- /dev/null +++ b/eBook/examples/chapter_10/methodset1.go @@ -0,0 +1,22 @@ +// methodset1.go +package main + +import ( + "fmt" +) + +type List []int +func (l List) Len() int { return len(l) } +func (l *List) Append(val int) { *l = append(*l, val) } + +func main() { + // A bare value + var lst List + lst.Append(1) + fmt.Printf("%v (len: %d)\n", lst, lst.Len()) // [1] (len: 1) + + // A pointer value + plst := new(List) + plst.Append(2) + fmt.Printf("%v (len: %d)\n", plst, lst.Len()) // &[2] (len: 1) +} diff --git a/eBook/examples/chapter_10/mult_inheritance.go b/eBook/examples/chapter_10/mult_inheritance.go new file mode 100644 index 0000000..79d1ece --- /dev/null +++ b/eBook/examples/chapter_10/mult_inheritance.go @@ -0,0 +1,34 @@ +// mult_inheritance.go +package main + +import "fmt" + +type Camera struct { } + +func (c *Camera) TakeAPicture() string { + return "Click" +} + +type Phone struct { } + +func (p *Phone ) Call() string { + return "Ring Ring" +} + +// multiple inheritance +type CameraPhone struct { + Camera + Phone +} + +func main() { + cp := new(CameraPhone) + fmt.Println("Our new CameraPhone exhibits multiple behaviors ...") + fmt.Println("It exhibits behavior of a Camera: ", cp.TakeAPicture()) + fmt.Println("It works like a Phone too: ", cp.Call()) +} +/* Output: +Our new CameraPhone exhibits multiple behaviors ... +It exhibits behavior of a Camera: Click +It works like a Phone too: Ring Ring +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/new_make.go b/eBook/examples/chapter_10/new_make.go new file mode 100644 index 0000000..27ed57b --- /dev/null +++ b/eBook/examples/chapter_10/new_make.go @@ -0,0 +1,27 @@ +// annoy1.go +package main + +type Foo map[string]string +type Bar struct { + thingOne string + thingTwo int +} + +func main() { + // OK: + y := new(Bar) + (*y).thingOne = "hello" + (*y).thingTwo = 1 + // not OK: + z := make(Bar) // compile error: cannot make type Bar + z.thingOne = "hello" + z.thingTwo = 1 + // OK: + x := make(Foo) + x["x"] = "goodbye" + x["y"] = "world" + // not OK: + u := new(Foo) + (*u)["x"] = "goodbye" // !! panic !!: runtime error: assignment to entry in nil map + (*u)["y"] = "world" +} diff --git a/eBook/examples/chapter_10/person.go b/eBook/examples/chapter_10/person.go new file mode 100644 index 0000000..4f60cfb --- /dev/null +++ b/eBook/examples/chapter_10/person.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "strings" +) + +type Person struct { + firstName string + lastName string +} + +func upPerson (p *Person) { + p.firstName = strings.ToUpper(p.firstName) + p.lastName = strings.ToUpper(p.lastName) +} + +func main() { +// 1- struct as a value type: + var pers1 Person + pers1.firstName = "Chris" + pers1.lastName = "Woodward" + upPerson(&pers1) + fmt.Printf("The name of the person is %s %s\n", pers1.firstName, pers1.lastName) +// 2 - struct as a pointer: + pers2 := new(Person) + pers2.firstName = "Chris" + pers2.lastName = "Woodward" + (*pers2).lastName = "Woodward" + upPerson(pers2) + fmt.Printf("The name of the person is %s %s\n", pers2.firstName, pers2.lastName) +// 3 - struct as a literal: + pers3 := &Person{"Chris","Woodward"} + upPerson(pers3) + fmt.Printf("The name of the person is %s %s\n", pers3.firstName, pers3.lastName) +} +/* Output: +The name of the person is CHRIS WOODWARD +The name of the person is CHRIS WOODWARD +The name of the person is CHRIS WOODWARD +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/person2.go b/eBook/examples/chapter_10/person2.go new file mode 100644 index 0000000..c58c015 --- /dev/null +++ b/eBook/examples/chapter_10/person2.go @@ -0,0 +1,17 @@ +package person + +type Person struct { + firstName string + lastName string +} + +func (p *Person) FirstName() string { + return p.firstName +} + +func (p *Person) SetFirstName(newName string) { + p.firstName = newName +} + + + diff --git a/eBook/examples/chapter_10/pointer_value.go b/eBook/examples/chapter_10/pointer_value.go new file mode 100644 index 0000000..253a099 --- /dev/null +++ b/eBook/examples/chapter_10/pointer_value.go @@ -0,0 +1,28 @@ +// pointer_value.go +package main + +import ( + "fmt" +) + +type B struct { + thing int +} + +func (b *B) change() { b.thing = 1 } + +func (b B) write() string { return fmt.Sprint(b) } + +func main() { + var b1 B // b1 is value + b1.change() + fmt.Println(b1.write()) + + b2 := new(B) // b2 is pointer + b2.change() + fmt.Println(b2.write()) +} +/* Output: +{1} +{1} +*/ diff --git a/eBook/examples/chapter_10/struct_conversions.go b/eBook/examples/chapter_10/struct_conversions.go new file mode 100644 index 0000000..59ace66 --- /dev/null +++ b/eBook/examples/chapter_10/struct_conversions.go @@ -0,0 +1,24 @@ +// struct_conversions.go +package main + +import ( + "fmt" +) + +type number struct { + f float32 +} + +type nr number // alias type + +func main() { + a := number{5.0} + b := nr{5.0} + // var i float32 = b // compile-error: cannot use b (type nr) as type float32 in assignment + // var i = float32(b) // compile-error: cannot convert b (type nr) to type float32 + // var c number = b // compile-error: cannot use b (type nr) as type number in assignment + // needs a conversion: + var c = number(b) + fmt.Println(a, b, c) +} +// output: {5} {5} {5} diff --git a/eBook/examples/chapter_10/struct_pack/structPack.go b/eBook/examples/chapter_10/struct_pack/structPack.go new file mode 100644 index 0000000..34fb95c --- /dev/null +++ b/eBook/examples/chapter_10/struct_pack/structPack.go @@ -0,0 +1,6 @@ +package structPack + +type ExpStruct struct { + Mi1 int + Mf1 float32 +} diff --git a/eBook/examples/chapter_10/struct_tag.go b/eBook/examples/chapter_10/struct_tag.go new file mode 100644 index 0000000..d9099d1 --- /dev/null +++ b/eBook/examples/chapter_10/struct_tag.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "reflect" +) + +type TagType struct { // tags + field1 bool "An important answer" + field2 string "The name of the thing" + field3 int "How much there are" +} + +func main() { + tt := TagType{true, "Barak Obama", 1} + for i:= 0; i < 3; i++ { + refTag(tt, i) + } +} + +func refTag(tt TagType, ix int) { + ttType := reflect.TypeOf(tt) + ixField := ttType.Field(ix) + fmt.Printf("%v\n", ixField.Tag) +} +/* Output: +An important answer +The name of the thing +How much there are +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_10/structs_anonymous_fields.go b/eBook/examples/chapter_10/structs_anonymous_fields.go new file mode 100644 index 0000000..a6a13b2 --- /dev/null +++ b/eBook/examples/chapter_10/structs_anonymous_fields.go @@ -0,0 +1,34 @@ +package main + +import "fmt" + +type innerS struct { + in1 int + in2 int +} + +type outerS struct { + b int + c float32 + int // anonymous field + innerS // anonymous field +} + +func main() { + outer := new(outerS) + outer.b = 6 + outer.c = 7.5 + outer.int = 60 + outer.in1 = 5 + outer.in2 = 10 + + fmt.Printf("outer.b is: %d\n", outer.b) + fmt.Printf("outer.c is: %f\n", outer.c) + fmt.Printf("outer.int is: %d\n", outer.int) + fmt.Printf("outer.in1 is: %d\n", outer.in1) + fmt.Printf("outer.in2 is: %d\n", outer.in2) + // with a struct-literal: + outer2 := outerS{6, 7.5, 60, innerS{5, 10}} + fmt.Println("outer2 is: ", outer2) + +} diff --git a/eBook/examples/chapter_10/structs_fields.go b/eBook/examples/chapter_10/structs_fields.go new file mode 100644 index 0000000..56d97f3 --- /dev/null +++ b/eBook/examples/chapter_10/structs_fields.go @@ -0,0 +1,23 @@ +package main + +import "fmt" + +type struct1 struct { + i1 int + f1 float32 + str string +} + +func main() { + // var ms *struct1 = new(struct1) + // better: + ms := new(struct1) + ms.i1 = 10 + ms.f1 = 15.5 + ms.str = "Chris" + // ms := &struct1{10, 15.5, "Chris"} + fmt.Printf("The int is: %d\n", ms.i1) + fmt.Printf("The float is: %f\n", ms.f1) + fmt.Printf("The string is: %s\n", ms.str) + fmt.Println(ms) // output: &{10 15.5 Chris} +} diff --git a/eBook/examples/chapter_10/use_person2.go b/eBook/examples/chapter_10/use_person2.go new file mode 100644 index 0000000..14447d1 --- /dev/null +++ b/eBook/examples/chapter_10/use_person2.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "./person" +) + +func main() { + p := new(person.Person) + // error: p.firstName undefined (cannot refer to unexported field or method firstName) + // p.firstName = "Eric" + p.SetFirstName("Eric") + fmt.Println(p.FirstName()) // Output: Eric +} \ No newline at end of file diff --git a/eBook/examples/chapter_10/vcard.json b/eBook/examples/chapter_10/vcard.json new file mode 100644 index 0000000..91d0da3 --- /dev/null +++ b/eBook/examples/chapter_10/vcard.json @@ -0,0 +1 @@ +{"FirstName":"Jan","LastName":"Kersschot","Addresses":[{"Type":"private","City":"Aartselaar","Country":"Belgium"},{"Type":"work","City":"Boom","Country":"Belgium"}],"Remark":"none"} diff --git a/eBook/examples/chapter_11/cars.go b/eBook/examples/chapter_11/cars.go new file mode 100644 index 0000000..82a56aa --- /dev/null +++ b/eBook/examples/chapter_11/cars.go @@ -0,0 +1,95 @@ +// cars.go +package main + +import ( + "fmt" +) + + +type Any interface{} +type Car struct { + Model string + Manufacturer string + BuildYear int + // ... +} +type Cars []*Car + +func main() { + // make some cars: + ford := &Car{"Fiesta","Ford", 2008} + bmw := &Car{"XL 450", "BMW", 2011} + merc := &Car{"D600", "Mercedes", 2009} + bmw2 := &Car{"X 800", "BMW", 2008} + // query: + allCars := Cars([]*Car{ford, bmw, merc, bmw2}) + allNewBMWs := allCars.FindAll(func(car *Car) bool { + return (car.Manufacturer == "BMW") && (car.BuildYear > 2010) + }) + fmt.Println("AllCars: ", allCars) + fmt.Println("New BMWs: ", allNewBMWs) + // + manufacturers := []string{"Ford", "Aston Martin", "Land Rover", "BMW", "Jaguar"} + sortedAppender, sortedCars := MakeSortedAppender(manufacturers) + allCars.Process(sortedAppender) + fmt.Println("Map sortedCars: ", sortedCars) + BMWCount := len(sortedCars["BMW"]) + fmt.Println("We have ", BMWCount, " BMWs") +} + +// Process all cars with the given function f: +func (cs Cars) Process(f func(car *Car)) { + for _, c := range cs { + f(c) + } +} + +// Find all cars matching a given criteria. +func (cs Cars) FindAll(f func(car *Car) bool) Cars { + cars := make([]*Car, 0) + + cs.Process(func(c *Car) { + if f(c) { + cars = append(cars, c) + } + }) + return cars +} + +// Process cars and create new data. +func (cs Cars) Map(f func(car *Car) Any) []Any { + result := make([]Any, 0) + ix := 0 + cs.Process(func(c *Car) { + result[ix] = f(c) + ix++ + }) + return result +} + +func MakeSortedAppender(manufacturers []string) (func(car *Car), map[string]Cars) { + // Prepare maps of sorted cars. + sortedCars := make(map[string]Cars) + + for _, m := range manufacturers { + sortedCars[m] = make([]*Car, 0) + } + sortedCars["Default"] = make([]*Car, 0) + + // Prepare appender function: + appender := func(c *Car) { + if _, ok := sortedCars[c.Manufacturer]; ok { + sortedCars[c.Manufacturer] = append(sortedCars[c.Manufacturer], c) + } else { + sortedCars["Default"] = append(sortedCars["Default"], c) + } + } + return appender, sortedCars +} + +/* Output: +AllCars: [0xf8400038a0 0xf840003bd0 0xf840003ba0 0xf840003b70] +New BMWs: [0xf840003bd0] +Map sortedCars: map[Default:[0xf840003ba0] Jaguar:[] Land Rover:[] BMW:[0xf840003bd0 0xf840003b70] Aston Martin:[] Ford:[0xf8400038a0]] +We have 2 BMWs +*/ diff --git a/eBook/examples/chapter_11/duck_dance.go b/eBook/examples/chapter_11/duck_dance.go new file mode 100644 index 0000000..43d938e --- /dev/null +++ b/eBook/examples/chapter_11/duck_dance.go @@ -0,0 +1,32 @@ +package main + +import "fmt" + +type IDuck interface { + Quack() + Walk() +} + +func DuckDance(duck IDuck) { + for i := 1; i <= 3; i++ { + duck.Quack() + duck.Walk() + } +} + +type Bird struct { + // ... +} + +func (b *Bird) Quack() { + fmt.Println("I am quacking!") +} + +func (b *Bird) Walk() { + fmt.Println("I am walking!") +} + +func main() { + b := new(Bird) + DuckDance(b) +} diff --git a/eBook/examples/chapter_11/empty_interface.go b/eBook/examples/chapter_11/empty_interface.go new file mode 100644 index 0000000..6e9358c --- /dev/null +++ b/eBook/examples/chapter_11/empty_interface.go @@ -0,0 +1,38 @@ +package main + +import "fmt" + +var i = 5 +var str = "ABC" + +type Person struct { + name string + age int +} + +type Any interface{} + +func main() { + var val Any + val = 5 + fmt.Printf("val has the value: %v\n", val) + val = str + fmt.Printf("val has the value: %v\n", val) + pers1 := new(Person) + pers1.name = "Rob Pike" + pers1.age = 55 + val = pers1 + fmt.Printf("val has the value: %v\n", val) + switch t := val.(type) { + case int: + fmt.Printf("Type int %T\n", t) + case string: + fmt.Printf("Type string %T\n", t) + case bool: + fmt.Printf("Type boolean %T\n", t) + case *Person: + fmt.Printf("Type pointer to Person %T\n", *t) + default: + fmt.Printf("Unexpected type %T", t) + } +} diff --git a/eBook/examples/chapter_11/emptyint_switch.go b/eBook/examples/chapter_11/emptyint_switch.go new file mode 100644 index 0000000..d034dad --- /dev/null +++ b/eBook/examples/chapter_11/emptyint_switch.go @@ -0,0 +1,32 @@ +package main + +import "fmt" + +type specialString string + +var whatIsThis specialString = "hello" + +func TypeSwitch() { + testFunc := func(any interface{}) { + switch v := any.(type) { + case bool: + fmt.Printf("any %v is a bool type", v) + case int: + fmt.Printf("any %v is an int type", v) + case float32: + fmt.Printf("any %v is a float32 type", v) + case string: + fmt.Printf("any %v is a string type", v) + case specialString: + fmt.Printf("any %v is a special String!", v) + default: + fmt.Println("unknown type!") + } + } + testFunc(whatIsThis) +} + +func main() { + TypeSwitch() +} +// Output: any hello is a special String! diff --git a/eBook/examples/chapter_11/interfaces.go b/eBook/examples/chapter_11/interfaces.go new file mode 100644 index 0000000..5c15bd3 --- /dev/null +++ b/eBook/examples/chapter_11/interfaces.go @@ -0,0 +1,30 @@ +package main + +import "fmt" + +type Shaper interface { + Area() float32 + // Perimeter() float32 +} + +type Square struct { + side float32 +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +func main() { + sq1 := new(Square) + sq1.side = 5 + + // var areaIntf Shaper + // areaIntf = sq1 + // shorter, without separate declaration: + // areaIntf := Shaper(sq1) + // or even: + areaIntf := sq1 + fmt.Printf("The square has area: %f\n", areaIntf.Area()) +} +// The square has area: 25.000000 diff --git a/eBook/examples/chapter_11/interfaces_poly.go b/eBook/examples/chapter_11/interfaces_poly.go new file mode 100644 index 0000000..80efb4c --- /dev/null +++ b/eBook/examples/chapter_11/interfaces_poly.go @@ -0,0 +1,45 @@ +// interfaces_poly.go +package main + +import "fmt" + +type Shaper interface { + Area() float32 +} + +type Square struct { + side float32 +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +type Rectangle struct { + length, width float32 +} + +func (r Rectangle) Area() float32 { + return r.length * r.width +} + +func main() { + r := Rectangle{5, 3} // Area() of Rectangle needs a value + q := &Square{5} // Area() of Square needs a pointer + shapes := []Shaper{r, q} + fmt.Println("Looping through shapes for area ...") + for n, _ := range shapes { + fmt.Println("Shape details: ", shapes[n]) + fmt.Println("Area of this shape is: ", shapes[n].Area()) + } +} +/* Output: +Looping through shapes for area ... +Shape details: {5 3} +Area of this shape is: 15 +Shape details: &{5} +Area of this shape is: 25 +*/ + + + diff --git a/eBook/examples/chapter_11/methodset2.go b/eBook/examples/chapter_11/methodset2.go new file mode 100644 index 0000000..886c687 --- /dev/null +++ b/eBook/examples/chapter_11/methodset2.go @@ -0,0 +1,48 @@ +// methodset2.go +package main + +import ( + "fmt" +) + +type List []int +func (l List) Len() int { return len(l) } +func (l *List) Append(val int) { *l = append(*l, val) } + +type Appender interface { + Append(int) +} + +func CountInto(a Appender, start, end int) { + for i := start; i <= end; i++ { + a.Append(i) + } +} + +type Lener interface { + Len() int +} + +func LongEnough(l Lener) bool { + return l.Len()*10 > 42 +} + +func main() { + // A bare value + var lst List + // compiler error: + // cannot use lst (type List) as type Appender in function argument: + // List does not implement Appender (Append method requires pointer receiver) + // CountInto(lst, 1, 10) // INVALID: Append has a pointer receiver + + if LongEnough(lst) { // VALID: Identical receiver type + fmt.Printf(" - lst is long enough") + } + + // A pointer value + plst := new(List) + CountInto(plst, 1, 10) // VALID: Identical receiver type + if LongEnough(plst) { // VALID: a *List can be dereferenced for the receiver + fmt.Printf(" - plst is long enough") // - plst is long enoug + } +} diff --git a/eBook/examples/chapter_11/multi_interfaces_poly.go b/eBook/examples/chapter_11/multi_interfaces_poly.go new file mode 100644 index 0000000..d98db8c --- /dev/null +++ b/eBook/examples/chapter_11/multi_interfaces_poly.go @@ -0,0 +1,65 @@ +//multi_interfaces_poly.go +package main + +import "fmt" + +type Shaper interface { + Area() float32 +} + +type TopologicalGenus interface { + Rank() int +} + +type Square struct { + side float32 +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +func (sq *Square) Rank() int { + return 1 +} + +type Rectangle struct { + length, width float32 +} + +func (r Rectangle) Area() float32 { + return r.length * r.width +} + +func (r Rectangle) Rank() int { + return 2 +} + +func main() { + r := Rectangle{5, 3} // Area() of Rectangle needs a value + q := &Square{5} // Area() of Square needs a pointer + shapes := []Shaper{r, q} + fmt.Println("Looping through shapes for area ...") + for n, _ := range shapes { + fmt.Println("Shape details: ", shapes[n]) + fmt.Println("Area of this shape is: ", shapes[n].Area()) + } + topgen := []TopologicalGenus{r, q} + fmt.Println("Looping through topgen for rank ...") + for n, _ := range topgen { + fmt.Println("Shape details: ", topgen[n]) + fmt.Println("Topological Genus of this shape is: ", topgen[n].Rank()) + } +} +/* Output: +Looping through shapes for area ... +Shape details: {5 3} +Area of this shape is: 15 +Shape details: &{5} +Area of this shape is: 25 +Looping through topgen for rank ... +Shape details: {5 3} +Topological Genus of this shape is: 2 +Shape details: &{5} +Topological Genus of this shape is: 1 +*/ diff --git a/eBook/examples/chapter_11/node_structures.go b/eBook/examples/chapter_11/node_structures.go new file mode 100644 index 0000000..f729d39 --- /dev/null +++ b/eBook/examples/chapter_11/node_structures.go @@ -0,0 +1,31 @@ +// node_structures.go +package main + +import "fmt" + +type Node struct { + le *Node + data interface{} + ri *Node +} + +func NewNode(left, right *Node) *Node { + return &Node{left, nil, right} +} + +func (n *Node) SetData(data interface{}) { + n.data = data +} + +func main() { + root := NewNode(nil,nil) + root.SetData("root node") + // make child (leaf) nodes: + a := NewNode(nil,nil) + a.SetData("left node") + b := NewNode(nil,nil) + b.SetData("right node") + root.le = a + root.ri = b + fmt.Printf("%v\n", root) // Output: &{0x125275f0 root node 0x125275e0} +} diff --git a/eBook/examples/chapter_11/print.go b/eBook/examples/chapter_11/print.go new file mode 100644 index 0000000..a394902 --- /dev/null +++ b/eBook/examples/chapter_11/print.go @@ -0,0 +1,43 @@ +// print.go +package main + +import ( + "os" + "strconv" +) + +type Stringer interface { + String() string +} + +type Celsius float64 + +func (c Celsius) String() string { + return strconv.FormatFloat(float64(c),'f', 1, 64) + " °C" +} + +type Day int + +var dayName = []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"} + +func (day Day) String() string { + return dayName[day] +} + +func print(args ...interface{}) { + for i, arg := range args { + if i > 0 {os.Stdout.WriteString(" ")} + switch a := arg.(type) { // type switch + case Stringer: os.Stdout.WriteString(a.String()) + case int: os.Stdout.WriteString(strconv.Itoa(a)) + case string: os.Stdout.WriteString(a) + // more types + default: os.Stdout.WriteString("???") + } + } +} + +func main() { + print(Day(1), "was", Celsius(18.36)) // Tuesday was 18.4 °C +} +// Tuesday was 18.4 °C \ No newline at end of file diff --git a/eBook/examples/chapter_11/reflect1.go b/eBook/examples/chapter_11/reflect1.go new file mode 100644 index 0000000..7e0526b --- /dev/null +++ b/eBook/examples/chapter_11/reflect1.go @@ -0,0 +1,32 @@ +// reflect1.go +// blog: Laws of Reflection +package main + +import ( + "fmt" + "reflect" +) + +func main() { + var x float64 = 3.4 + fmt.Println("type:", reflect.TypeOf(x)) + v := reflect.ValueOf(x) + fmt.Println("value:", v) + fmt.Println("type:", v.Type()) + fmt.Println("kind:", v.Kind()) + fmt.Println("value:", v.Float()) + fmt.Println(v.Interface()) + fmt.Printf("value is %5.2e\n", v.Interface()) + y := v.Interface().(float64) + fmt.Println(y) +} +/* output: +type: float64 +value: +type: float64 +kind: float64 +value: 3.4 +3.4 +value is 3.40e+00 +3.4 +*/ diff --git a/eBook/examples/chapter_11/reflect2.go b/eBook/examples/chapter_11/reflect2.go new file mode 100644 index 0000000..7780228 --- /dev/null +++ b/eBook/examples/chapter_11/reflect2.go @@ -0,0 +1,33 @@ +// reflect2.go +package main + +import ( + "fmt" + "reflect" +) + +func main() { + var x float64 = 3.4 + v := reflect.ValueOf(x) + // setting a value: + // v.SetFloat(3.1415) // Error: will panic: reflect.Value.SetFloat using unaddressable value + fmt.Println("settability of v:", v.CanSet()) + v = reflect.ValueOf(&x) // Note: take the address of x. + fmt.Println("type of v:", v.Type()) + fmt.Println("settability of v:", v.CanSet()) + v = v.Elem() + fmt.Println("The Elem of v is: ", v) + fmt.Println("settability of v:", v.CanSet()) + v.SetFloat(3.1415) // this works! + fmt.Println(v.Interface()) + fmt.Println(v) +} +/* Output: +settability of v: false +type of v: *float64 +settability of v: false +The Elem of v is: +settability of v: true +3.1415 + +*/ diff --git a/eBook/examples/chapter_11/reflect_struct.go b/eBook/examples/chapter_11/reflect_struct.go new file mode 100644 index 0000000..2d95a25 --- /dev/null +++ b/eBook/examples/chapter_11/reflect_struct.go @@ -0,0 +1,47 @@ +// reflect.go +package main + +import ( + "fmt" + "reflect" +) + +type NotknownType struct { + s1, s2, s3 string +} + +func (n NotknownType) String() string { + return n.s1 + " - " + n.s2 + " - " + n.s3 +} + +// variable to investigate: +var secret interface {} = NotknownType{"Ada", "Go", "Oberon"} + +func main() { + value := reflect.ValueOf(secret) // + typ := reflect.TypeOf(secret) // main.NotknownType + // alternative: + //typ := value.Type() // main.NotknownType + fmt.Println(typ) + knd := value.Kind() // struct + fmt.Println(knd) + + // iterate through the fields of the struct: + for i:= 0; i < value.NumField(); i++ { + fmt.Printf("Field %d: %v\n", i, value.Field(i)) + // error: panic: reflect.Value.SetString using value obtained using unexported field + //value.Field(i).SetString("C#") + } + + // call the first method, which is String(): + results := value.Method(0).Call(nil) + fmt.Println(results) // [Ada - Go - Oberon] +} +/* Output: +main.NotknownType +struct +Field 0: Ada +Field 1: Go +Field 2: Oberon +[Ada - Go - Oberon] +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_11/reflect_struct2.go b/eBook/examples/chapter_11/reflect_struct2.go new file mode 100644 index 0000000..2c0c915 --- /dev/null +++ b/eBook/examples/chapter_11/reflect_struct2.go @@ -0,0 +1,31 @@ +// reflect_struct2.go +package main + +import ( + "fmt" + "reflect" +) + +type T struct { + A int + B string +} + +func main() { + t := T{23, "skidoo"} + s := reflect.ValueOf(&t).Elem() + typeOfT := s.Type() + for i := 0; i < s.NumField(); i++ { + f := s.Field(i) + fmt.Printf("%d: %s %s = %v\n", i, + typeOfT.Field(i).Name, f.Type(), f.Interface()) + } + s.Field(0).SetInt(77) + s.Field(1).SetString("Sunset Strip") + fmt.Println("t is now", t) +} +/* Output: +0: A int = 23 +1: B string = skidoo +t is now {77 Sunset Strip} +*/ diff --git a/eBook/examples/chapter_11/sort/sort.go b/eBook/examples/chapter_11/sort/sort.go new file mode 100644 index 0000000..00f618d --- /dev/null +++ b/eBook/examples/chapter_11/sort/sort.go @@ -0,0 +1,58 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Sorting using a general interface +package sort + +// Sorting interface +type Interface interface { + Len() int + Less(i, j int) bool + Swap(i, j int) +} + +// General sort function +func Sort(data Interface) { + for i := 1; i < data.Len(); i++ { + for j := i; j > 0 && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} + +// Test if data is sorted +func IsSorted(data Interface) bool { + n := data.Len() + for i := n - 1; i > 0; i-- { + if data.Less(i, i-1) { + return false + } + } + return true +} + +// Convenience types for common cases: IntArray +type IntArray []int + +func (p IntArray) Len() int { return len(p) } +func (p IntArray) Less(i, j int) bool { return p[i] < p[j] } +func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type Float64Array []float64 +func (p Float64Array) Len() int { return len(p) } +func (p Float64Array) Less(i, j int) bool { return p[i] < p[j] } +func (p Float64Array) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type StringArray []string +func (p StringArray) Len() int { return len(p) } +func (p StringArray) Less(i, j int) bool { return p[i] < p[j] } +func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// Convenience wrappers for common cases +func SortInts(a []int) { Sort(IntArray(a)) } +func SortFloat64s(a []float64) { Sort(Float64Array(a)) } +func SortStrings(a []string) { Sort(StringArray(a)) } + +func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) } +func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Array(a)) } +func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) } \ No newline at end of file diff --git a/eBook/examples/chapter_11/sortmain.go b/eBook/examples/chapter_11/sortmain.go new file mode 100644 index 0000000..da63508 --- /dev/null +++ b/eBook/examples/chapter_11/sortmain.go @@ -0,0 +1,82 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package gives an example of how to use a custom package with interfaces +package main + +import ( + "fmt" + "./sort" +) + +// sorting of slice of integers +func ints() { + data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586} + a := sort.IntArray(data) //conversion to type IntArray + sort.Sort(a) + if !sort.IsSorted(a) { + panic("fail") + } + fmt.Printf("The sorted array is: %v\n", a) +} + +// sorting of slice of strings +func strings() { + data := []string{"monday", "friday", "tuesday", "wednesday", "sunday","thursday", "", "saturday"} + a := sort.StringArray(data) + sort.Sort(a) + if !sort.IsSorted(a) { + panic("fail") + } + fmt.Printf("The sorted array is: %v\n", a) +} + +// a type which describes a day of the week +type day struct { + num int + shortName string + longName string +} + +type dayArray struct { + data []*day +} + +func (p *dayArray) Len() int { return len(p.data) } +func (p *dayArray) Less(i, j int) bool { return p.data[i].num < p.data[j].num } +func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] } + +// sorting of custom type day +func days() { + Sunday := day{0, "SUN", "Sunday"} + Monday := day{1, "MON", "Monday"} + Tuesday := day{2, "TUE", "Tuesday"} + Wednesday := day{3, "WED", "Wednesday"} + Thursday := day{4, "THU", "Thursday"} + Friday := day{5, "FRI", "Friday"} + Saturday := day{6, "SAT", "Saturday"} + data := []*day{&Tuesday, &Thursday, &Wednesday, &Sunday, &Monday, &Friday, &Saturday} + a := dayArray{data} + sort.Sort(&a) + if !sort.IsSorted(&a) { + panic("fail") + } + for _, d := range data { + fmt.Printf("%s ", d.longName) + } + fmt.Printf("\n") +} + + +func main() { + ints() + strings() + days() +} + +/* Output: +The sorted array is: [-5467984 -784 0 0 42 59 74 238 905 959 7586 7586 9845] +The sorted array is: [ friday monday saturday sunday thursday tuesday wednesday] +Sunday Monday Tuesday Wednesday Thursday Friday Saturday +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_11/static.go b/eBook/examples/chapter_11/static.go new file mode 100644 index 0000000..032ba04 --- /dev/null +++ b/eBook/examples/chapter_11/static.go @@ -0,0 +1,23 @@ +// static.go +package main + +import ( + "io" + "os" + "bufio" + "bytes" + "fmt" +) + +var r io.Reader + +func main() { + r = os.Stdin + r = bufio.NewReader(r) + r = new(bytes.Buffer) + f, _ := os.Open("test.txt") + r = bufio.NewReader(f) + var s *bytes.Buffer = new(bytes.Buffer) + r = s + fmt.Println(s) +} diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/00changelog.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/00changelog.i new file mode 100644 index 0000000000000000000000000000000000000000..d3a8311050e54c57c5be7cfe169e60a95768812c GIT binary patch literal 57 zcmWN_K?=Yi3H!bC-$VY|B>;1R$dc$2Us+p%SU;%j`vHws2WO62_=cEZRwS%Wwl_;!9GC zOR&g+bQPBtV3FbQP0UVB%gjkdH;xUc1&exiy^Qpd#PnixFW6PDq@o0yc_o?H{0T7+$j(xnma}OWB@^6_a9^KoXyC1^zFqxmqEo$NE-V0odGfPiaDLFn) zAX8im5KOu{JxXHbmROeFM57NZ;&`)9QQ$ITSm<0((RVQMF@fg+@=1X7xML96`o|Z! zXTcmNhQoo2dA+gHF>yyLS|Jf4j6}|4!`;kmyMFE3na_yPU!o(BE=o2BcXj4`l^tWg zwAIUBb7r@Hf9OqkHZ`h}L0T4Jsa2x+0W0j6bb)VglwnPjq~WF(F-Oka_6kOH zYe%;RX3U2otL54rGX~&MM)$i}2tD%Zvlnn&`w*X-dz(c#{Qh?hZ6v^zVP=a=hLU@IKcafX27VqI;W!aPlj@&o; z>wDluKo0jvJ?48p{LpXn-QA<2ZOYvRDW&P9;dG}YJSoMbI4$fgvwgRJ-ue6x`Tom+ zg{r-7G}+Id@fY_e??{*`*DJ*utz~vIY1O2gk<~Qas!#WM*B-~>)5#nxkPx|M;UKVq zUmAYo7DzvS$^ZA6`^zGJjOe9je<$z`DgKO_@a;%uJV)va^4GhJvEHeSES(XprZf(0 zGt#wn{q(5jPCYajr{(grBUhC$=g z4jmkFB)VD*`kWSp@Vl>FKn`=C2JU-0eAt9^Sq4^&A}60#`~l1=d_0t?nM{J`_&BRA zaC|HyIXTmTu*lACs^Zi_ibegEF8|t~tw9oL&)I;X*@o}~(}9zAHo;pfw$yE#q{1^e}6DJQKfhY{8(g^u;@J9$p zpakrtK7D8sqRS%x^mt0IcFvf4UEu(zyfNsdPZ-Axm&1>i4&K4pph$h?(!Nvk?B`U8 z72U~r8%lOu)iJKLuZtNz&cpNNY?~1IpLy%5>5dFeCCoa=&$H|})W(FyE0y%v*;g&< zA7n>g25gE4l3=V0ebG%PFcDP$(3VP@T3@at)mL(R?sh5036AmF|VuW%$)3Q7l_Wkl#hK!V4~R>asPlQh!YEq{|?KUKwzM|m4ncq_^7q(AA+!ji}m%HtpPIzHx~(;mGP zc0QZ-dBpg`k}}XqAG;xn8?D2sD$LDNW-I6+`Qxq-Vqan^*G<`2(t3>t2@|qNsJt1A zmG7pyi<@v?ZPASmRf`uKAk9-mpc0r;Pc%_wQ$px5Mz}N*q z22F8iq;h(0HC#%d#TLEoS*wPVPGmDwcVkfRCu%|OE>Yy~oNz1?EEM)w{vg=6^=V*@ z5@wo=NZwMVr_JY)dv6{--Oilqx|e5K8l|U)&i5JJKHz@y#20PT+T)3o3dAq9p1sTT zS!uZzFro^Uy@BjFFc%8N2#$AcDvn1~Iz2xV=mn((` zXY}akyXKbNG&Yx~Lu=F6t-`b&c$TXoHZUqaXz&5P$YyZXm5~1h0Z2pz zC6MXci04|qNHb^H8{v1*v;8u8po|r&yD_N86Xd}VRet@0J%-cLMAAUXZ>gJ5GmHTv zDpF56GJ2vYkf_^lm5KLAF!1?Z!?z2>O>#qG;i#DB^S{(}IS`gVVi6TmdpX4Uc8nb| zM`Yqm2-+FQ4GiW@x73t)dV59N3$qaYO%CMInsKrJ%gQ22@_S#zy!rC2;LE8X>Pc}1 z_pOAy5BLoH@+fK(oD31P)tQVelv3?>P4lm3vJ^CDvp29ZBM^RJ6BjuQqPL17JG$2P#PxHXR@Qf2w0cBuvpxmHzY)1W860Pn22Vx-G-0rIXfTRHB_NCrNba*8z_!-*_(G0_yr-*!DoLw7(1;?FQ{I5g>+9ua@(z;_I5*|li*S|!bpz)nL? zoliME!%ZT?(b9Gca=TBVJS;w9AnXt|WQf~PNmQ$a!+>U)S~#I{FWHU5|lt*UVkTYSnRFVRxIbFd(h>1nY!gB?m@aj*M!-p$7#@`_`3DUKm8Qt_+ zx&o=mHiPZe&w5x-yS*ze2>g*e)kCoo>iN=KzipsMq|3)cI$)?nz{6@FY(oIrFhL2l zb^9KM%OVNUFROL5w=RehNu9a9g6eJz8gIk(KpU#HgDBzZ!)#A{td^z+Sz@Oor53d~ z-LL}TKgfTaWzv;RI@gAAuC7=I_gfg{TWl5RYMBbtjIi?PIZau_dE-;a$&IEENb4WQ z`!tPsm5_~Nl~}WS_xF2b)J%Rs{}mE6Cnr<czUE3nunpD zcm)w**k_-b`7`_`TplzP5sguw`4KKp;@~*q9q(cwWgcUNYD+x;tkL}8+@m4?0s_`G zFoD?6!SlMk_$2{9mX|!J?+t4$Enoe6-{F4+yur+|=I|kRf5OHCzK&%TYSnv z6xEi|6?0{~=2TFS&sIVyi^_=!!|^^TYSU-+;h4flWeL+v#d(rF0n29k%eyZoG`GF) zWc{Jx#&KN!c&jkWZs}z1td@nO#BF;N!7G-Z`<4-j>|Dd;CyjOD?-BHWYuAb4wEN>03!;~w>?JsfF&A=> zy;3{)rwS+9{ogmow+g!o>oZfo#L%*ES(>q+BHy>x=~iE5eSZ9{RK=$!^6eRA8s61P zo`=@L6t7|@x+i&_qr7|1Jp?=KTf0x5Ayzw}PFM9YwvjoQ&}z(f)h?0Ri?RTU=oxUL z!1qDGxdt{+=5Hcz9`uQFkzK!3;^0u~w@TjQAMm@c9TZ|l8yXY{c4 zWoq`b@Cjo*a#g{fkDfi6B911MIV>sGT!#- zIQz2R=chFISY|=azT3X8BC_6oh*q4^--oUCilb;szL0Z%$w#eHVHYY@BO94-c-Z%l zZ%)CP-!UB}x2j^l)h+f-=~MF~Y+8oPA75v<*B}3!&|PF-f2FhWG_X^LMdk1tPFlRX z$+oWJV}HdTgKH?wMUV2FlsS0mc@3oKsTU>to}Kj+b|Ge3sA05wq6`aK2vs>1tbKZf z#J8g=542z$!4*|NegOjBHE=-_q~>C%?fawj2$_zPr%n1kMapSQhu?kepe9HJL6k`8 zw{+jzP!l#?)%XKMx6V*@A9V_Ibw`_T+cgxVZVm$O{DKqD$|vP#kVJLMgNih){JW@> zMOFFLZ6=yV-1GI*H5w?iM?1)Nk4A2XKfL*crb%ITaasr-km`|Q|7|~f>c;T<7NRK|+X>%;_JiWf)a)&U*8x!7je$f>0|-^7 zZj2j?k5w=?Gjniz7b{tQEFUvrE6epRnP>8gi4ZQfsCZx?tG|b6wvHbbaks*(LY2`i zqXu=3_ZX`=0vwAeu~^eNy6TMvGAuN)k_E!w6l@hH3#$3XvfN^9*tEZ6y2`%Wzsl=u zyt4I~9ttF#<#`ocKlfCFGcVRyA*B|uuEUNNKO%Y^gfA*${dybe6qUunMUqL5?mU?4 zy6H{nE=v8Wv>G6Z{ck?=fG)um;WY?=x|+QL=@$)X$@ zH5Hc6@01vYEBF&5C%kMM{px?yj(b-Wb{ZO|kN2F)A*lXbuzG@=;WQia{nyt?f6=!I zfi>06ti(%yLfUwTZ!<=KXJW4d53_&(l4QV_2$X=Yz}|TlwbvVjuY@lAyVhKLC6a@$ zp}HFj$e|u;#|ecdgFCjy2=oXmwWN2+adacYEF;_gjPu1GH&j%bo9PWR z;!S_(gFu$Dk?DJfPcw5sA@0e8hS2Du4m-RId&%0(A7u|?ew1a9hCU{00uRA~$22%E zFX)fN*B}Di=A%wLl523NRJug?{!+zL6)yWbfxq*g1?1rL{-3rK>Cu&g+A@^VosaJ= z4tuj!6OUBan?5Y6H0AtcR(wq2vhNR7$;BIM=}Ur2Z#hU?^Io~_mu?+?ENI%F5gXGa zx**#fyv^YK0!4p^ZzIh2uiPGwZ!&qy*oE(I51zX=gCck^P6Pb$Mvw>#94>M%GR)1%Z4c$P#ll1NZa!J+E@N zw6y&b&K70*dOROwc_-(~mmB)jg)5uuXl61v*+_1Bca-*>ts&eR-_b^#m-t~Pb%OHS z>=wveV7Oob@sAN;MS2Yq!0Poo6oFp$hB8lyaf@N1$}; z>#`4s2~?DujE08yts|a^-QplBPN$KOwpjXB?;=na*A^P)&2*4Zfl=}V#f72}l~<@c zsJ#8I)LZWv=C@V38&^nF%nHZJx$X70Bd16gMMLk*?Ul{!ws(3NdtYqM?_o4^(W!#x z;{J=)CeURd1i+UJlz{I{dzWGA?x)yqY{j$)mWpv>j(hNB6I2hkn^uI~aZa?hcd==B z7m~kE6cU(-h7*GLnh+OKo?t$ky# zX_Mi1U%P+p2xWx-+EFPnyEGvZU$8E0PwdW2E%N%iT*(O2I#jcMX-aL|BAHFR-KsSr+;g)UZlV|GMoAh7Hs;3Tibvwc0Km=jD`6_!kHL z7z>;K6G;|+NW-2L`f0&v$oLzNg-}qF3ZsM=S(yRl(T8MhS;>uU*#M)EIpMTD#f+#6 zZf0%WQ>1CV&64*|)hVJ=*6h1W&RMKehP!Uu1mos^Qgl>V6)(*&e<5 zE}p;=X&os14mGD`i!S(M{w=*;rP#?=Of=8eoyP4yj&Pq;>s{nU^@n!za&jG7ONHi7 zZ8#3d?w=Xh6Rvzhd+U~LG9`WT-s_6l^`fWCi`7ULw}t&S#1n?E1UxJg0?4%icPdZ< z?jm)(f6AAaZkz2;xgx=8DExJ+*`T@`1C!m&PRo2p9d47se7o=gu0v>;(Bv%a7pB!> z#jAMPz_Y>ZLH8^jKgzCFj_^ipoJs3c>!5I$-rw%TEFpY#I&$+68U9|2;)bEb+eHcU zzZvCrrW2%S-prJ&8(VOu{kdRWvouliSn)7XsECnZ)m(i)0;pHEsXx> z!JB&oi{(E}%6;7TRV5YxL;Npro*+B<2muJAhCl^`k$dtP=BU9GyePGnx8yrg>7`2VRJ#`A;YnNy>3- zMt|LD`wK(U5`b@C-TDouTaQhRo9B+|Fq(jX z9`Wb!N55dGjFchZ;RG&l3NIiJVi(;tXaVPBudWp#-2z|ZSoM*N$(;MEF=Df$_yc0=B(J!8rvORO8nZ;;vdF$qVfY>@K1(GQkA=pcY z!N4*Lq~vrE=s^i&6}&q|<+&%(M;qWtkA!+D9cYpR@`W3NMt_1dkfkE|8ynk{obAlG zu^T}QNg$T661Du32U;6JSq~9^zFAPi`5PTC!_me|d|w~d^|Tr5aNR;>``oxElvVA^ z4QXUevAX(!x20m_Rqvbel<++$;@WK1ISYFG0B^!>SK#u;zVp=HT`DYXdz)!=EYY-u z$#K>L2BW|De05$bD&mQ`(IcoorI{WqS$~p&H#{MDtzfWx2q1%DxCT8?rFH(0{Cm=c z>*De2CrU%bYZU}+oKXFZL8?ZpE$F+D0rm_kanf;@h z8?OBrUnITk3XI(( z1E}uCK+NU`y{0Vb4cn;3PVMJsSrU`m57pzuNK=;(`i%OjFVMqA!6fL<)Ze>qS>t;~ z4{Vc|c0b%vNM|e}l|yr+$HC4B=kxiZGH`#r;F#p}UZ(W31<5JBLn3CXH@eEWdA0T{$PzlJyGK?YO)3Q7@$M+22Lst@{JIfuE7XY5GfYi z<$scut>Hysko47BK3A0v>~q~1c=!IzJm4rJ#+p-+(C%{(rr;j7ssejG8KDkuDd+0O z)z#8Q#6gRHdJg@*2lBpfi@4uJFjjg1qL_p&zpQDVnT0cxc7|HQ!6T9lzEE;hG@~C9 zRm~X+W}8i4)uYypKXcUn8Ykhp%lfL_E5O=5CG)P=dN`#a_TiF@{)qe|*avD!KR}5X zo)yAcq02J}KnXJ_fs%qcr>o*&CwcnL30m#UwH|vG%2TNB#vmn$Ad$g-BE8Sc*mJI*$>)y=QWhS>2P&;m+M%?%uyfzG=fUqf*mYh~eR$O`p24H}c{wX~PBNb6 zO8_D5ijPNxJlpW9OjNYf`E#NgigL?UM2y8&39+x? ziPo)nUON0n+*P*)@F%{4t9S?b9SC6S4uBcR*6G}EL^J_UR5#A zj6UX{j97%HYMcDIw=Mm;GQ@k{CktDgwNWlTiR*^^_lfkJuYQV z!}~axN?5lO6h7LhhFv(_9p$@36D`ebZ90F|SEf5RH}ccNAMpjfL+O1#jDTG9!w)|b zy^mu<)4SAMj!>l2_}2h4Qe8N|JjjC)3UWOFRv>6k`SzXX&mw7B_16SRjX z@lZY7K-`2ME+Q{WLt6v0moRQMu$<+!4wd=YM}pni@$-0=3?4Wa<7wgz)w5I-MOEpm z4VEbF&%E!;w})yCp6R=?g^0Xl z2kRji*?l+<5CEGX0OA~=1jI*b{71;E_h`L;8kFB%s_M|Wz4brKO~YX=_;&d6tKhf= zOtb8_m&^Tv0SK9zr6nd=DaApE`>vIoXfiZXOGJIYaV2eveKFArCT7fzh0wL87=}w- zH5pNBya>_*AC5kl#aL)n$!^j2(9^PfAvBh{dqz65b@eoOCF4ZoO7CQhM^xL~#9BFM z`NOi9UdHTN&n*uq$GuDN37w3L|ULj+oT`(7|pDY~HE|{o-mUc8jFdPntpCv`j@fBY3yN`*n7EA z${-10cs5J^6izG$@?gsssNe!6P-3GrqDSlIwT-D{FFHx&`OG9Fxf-gwv49-uA$Tl! zVzZI=-nI~l*_BR~a(8#cX(cjl!T=|V^PO573y-Qv(Au|P(x>}rg0D=g{3?l;)QM(; zhnrIDApetwglViEa*M zXloahYTr`Z4yBAo~qavn{ea4oW_a@Bka`7SO(@iDx4}+s*%3NB3w#E2tPj;zwSzyfx#k9s&UFv2p zEV1YI^-W1T8%dw6?JMdr%&=vni zdL~o?(mbF9r1hWkQsfEzVWMAJ3`tSsEEtj-`Jd(A{{-ii^Ji{#o>*&4r3MNpw~S*J zpTCPN(a{MC`q8oPn)OsfT&y;JD1%L0+F2pu?^Z->7+3vD>WAOH56f+dg%S}G6n3m# zI`tl9x!FJ34dK`PeYL`6QQZ7X)Nmg&QQZ3p;j})(^LH-koYliz6SMZGuwS=0`XRC~ zN|21hU?9l=s}SC6@Bk45YCrQGoSuDsG4rsFB~gpPTeB1Fjo#S*?A06OOv=XF!U zjuxLy%&P9ZpLSWnCDMeMeFQ3*W(aWmD#9PRHeOf$2-wLk6b zUW{m^%PNl!BbqBmYG}ugWCh*TrRyHJ$5(+?d;znR?9MH6p35Bv!T84D?+Z9gjrO*p__ z%5T!AE2t@0o@$ibV*1)SdY9;}B(1K5L4Q%5x;0~3ii&9NE8nL}nO3KH=gZA(;vscm zxw7=gr!0S)+eD zpCZc+LiINW`auJlI-rd;_|&0WCB(0iq~}QAJ4t`E5D=vGxzkt;f!>iAJ4YJrU8-DR zgTWiVpdpXS_>JbOuFE!eOP`h2w$HMngbd7@{P+to`FYGWy1+Pf;?D11I7ZN1dLU>&a)&2(hnc1I+Ocz7GraN@%;ad zS#UUvuRQtD6e&viwmhF*k}P$$HNx0PZyX)14Fb;7fiPC;t__h<_h_6H?>9;8CM_9E zbal)LyG3^H^NsX^p*=1AFDh$K?#Cb?(INW^Y44;TK4P2Rer##gl2xhG{F>xWW2a%@ ztHXcIbVm?L7&RI2uy6=KjNml{0QuR)d~%U!a!wnf)H>Q=LMBr( z%t)yI#{M<;^#^)T9>V^1s+UX}^Cbc+`vlSVe=j|fm4wT^I)#8*>*QhV@_V}0`X*X> z?12+0X@qBc19rN-qcdWGe?Bj88CBH~C>%W%f^n^J|MI#JUGJY4REh7@-8T^2-%K3H z4w4j`2|M$MFk43%sOpn>gs@`5{Sr{2{H-qTm{&pXf8*00#( z#`i>u(|ar3?W-sv#Gg4AJPXuyY}z)HS9!iQWFce!WMtiB$I6Woe$9Z%qA;_w$-(Ir_|9}RcN-sTIQ+=kzM?f$2K z80_y^6WDz|A$zEzP~GHIp(WMD;Sp zN0&pM!Z63|xEA)4&R^-e!-V;>3~B7Y0xrvjxO(R$UI_c7C*Za3Vb$(;%(M?O7vE>A ze)DOT4IWWx8sR)*ArEG3KwSisfck-iP;w;_R+A{bS(dJ3f+{QH!XK#a#-Lrn(Lo$& zTtt1#(eLw6vi0m_elrOpl^|PGB&9B1aO2?x_2o)& zEowT^re|pL^@%PcADa@sk9X_MHdW0nPsXr-rwo#mE6BU-l$jpe4R8RCi;Lgdz9_K-9Na!I-w6+v>CnumvS~m+4iI z6@*Hhs%UyRHGVPQUD|NZ`ie_Qj$Yl?O;Dih5aSp{UASF~%1kl)uGrFi)tk7|vNm%9 z0jE3>6~XK!P4_SqqBzW{t8|**t_clOxH)q>W4kv?mGQkjOc^d`Iq+A5PKw1288QGB zI(axDkQIR_D}D_zpnz034_Ox>zRdi~Cy6w~W|^3;_Wu*8aC-0HM$kd?!ei}8tPvtI z_2+%Nh%|+%&N12vE9tw(i+=;GxICN0{9>7qZGD!KTWOxRDSZexCCUx7#7ufTZq~rl zxxtd=?p|Fq??=`{?e<1l2x(j*T{(e#$j4&_+c&~c*2C&G&AwNsKV>bqt?yuoX*NL$U%v$W! z&QC&=s@QyWeD6a)&$AN~r)BM)OR&cvXxyIdYJff-GUc||sW2*KoX*G53o44DKa|PW z7jbN=BzfSInbf+#EUCJl!{3~SIoolo@c2SZ&{g|%nJ@l)_^aWs>BpWLRMS%%cjtD~ z2B~imM%pA|oGW4Lhx*(X6U4c7l2O<5!Q&xI9#YV&CEp_v96*xZ2u>A5CXfS4UPA(C z%U1LawtiEYNrsJ@p@{b3-2*x`3;5mF4rtTBM52eLzV<2)q-}#UMf%8UdP;QXw1kQJ zZjtBJGEd?K0!hb~p80K< zkJ-(x^z^WpI`qTNZ06WouANJ~r0#*!$~N!Vz}>DE!!c3v*o?KUdg|$&rNnilp>{ra z%%NX|GXgQH4FV7W2D~H?F^t$l;AFExy-UN-N=D43)$2z26{@>2`02&<-ok^=?-;4& zFq~2x5c}OcBG20h2%L1Op0!~`_w`NPmmaR&xty*&et`6e?enezS-6%uW>IvEpMeAg z`>11~aY)a);OqJtDT&P{k5BKc$mwS{qaQ6e4UL;EWh{H;TDQ^(j}dSGa+I4#-_WB! z@{Km}I?*Vk2~b?+pbnw@%c=!9F*v}PWkVi>V6Z#|kOETf-$lf4h>Udo`P}|q-QE*^ zo~`m?sP4v~{)oQ=(m|yw@jfd#uGI7tvLdvf*riS8^YiKoFUX|3@Oz?V1v7uAY}eGO zw-(f9mEx*U&N$h3NPKjRXdG%$30(I{CW)M;AZ1CKlzFr;y=h^fhhA`xS(vJrq|ie# zXOh^~kO2x=tJ}5FJdHQbu@&YPUM%NNKEi}&%TPVsphRX2t`K}J0-ZUbl{Yc< z2cY3uvuU~za^Yw~Cr%&Jwl{Px%{AZ5kffz(qY8g$F@D4N)k(Ri<>X$xqM+kkFwuCz zvc>9S~^2CKTkc+_v1Kf zlA{QtMRw87c^Ieb|F9rro~a zeXV@1uL6-C^g-{Tx*PlN07^thSW`qzSU|f`m0y5gSY1=Sg-=6MT}V(=M?+AjUQ?q* zNJmh+N$4B=0E!75K#A}P)zt|J3L5`+00r~J>$QFoCHD{`Mp^18#amrpPoK!^=tw~0 z@TtJj)GyeU5(PPUGE)Wo`T3BafdB}DnMV!~-ksktT|P&ZGPa}p#qh~JKi>rFf3kVY zq5pP(UZ23ab9G%l328NYS7;#)s>+}F2W7Yr%sSAP zu^PMxfjsCCg=@$IeJ@IFN`0>kb+>2t7Ps#`6XcFh```7||NSDDf8T(ukTv>S)|x@`N!D z01rQtU4Tl!UJ;alJ?x29_AeUI4S%^G*g*`YpYTyc^`N>N15rQ{7y5h!`gmH~#@9J| zN=g;OoOhz&wyGvNdTKt?=c3zg`CQOO@bIN2QScX$&KEcZ<;)ymZ0M8H?rjs)f{5)l z7V6y2pVGz8hh!F_ycAq!r&yzdd(hb@$GUxz9#>U=ojUQ5rjCeRyl67-@jAy|5PiNs zc?Jv78qR{Dtyjn9Tc8d03Q1tSL6Z*7ISJ&KFPVI8asgW^kaPt+S^mXuFcq~zP`ZX9 zkeBhplWLL>gV!-l!QU=v}3}@@@jgaMq{PtDh`ZgGpA2!N&B2(KCB8!zKyo^~qkmr^|R z2qu?lbC3)IoLCOv%zPl92?0n^1|^V^nuJy~z;0i_h;}aAUdABX^5Z2cRCi3SeA- z=~Lwz%7AmvFT6JE2OG2YUC7-}cl{O9xK+XKg-XyWc$kq z*s_X>dJ;IAmH|P+uQWyXnZG_O*6qfs`S`3*MqyT-`f7Ic6b~<41r3D*&4v4M!k2nj?K2Cy>cHH< z_e0(b95VD?pPd#ff|2kx6+m0VSbxFkEknN_0fQgt0SiPGpeG&8I=q3u(daAH;y$K+ zZlrX)P#9EqW8igq3w;EQ9qs<6?B|f&AaluM5i)XufJVURy%%ad0y9Xc-8pRFyL{a+#O}zUuyNXz$+|WBUCmxE_i`WfJniMvh(_9oO z7P9isv9@|DC3Va-I%_GSMD0Pkw)e7$FCHycKE3nX5&Jz5Aq3Z<(2O z+=Bj%RxQ4$(OQ?vi|`qqziV{2+-?zgu@}SUKhXtu`umGAAW8J}Pw<%|KC5q`y7=?e zx21&U5aEK6q!~Ph9c*R5V5tzm+X&(|fGS{@ggKb^Sl8V)(msjTsYYnH{PQ1nsP4v~ z-h2Ar@6T4KSG=RT>z* zSK}=dByCDvT>rodW6azlIMLu?g5rl-EW#A5GOAXJM8CBh8;;1!r$OGZ0U8ZbkHHM@--J@E#aaI)^4a+!=B;PNqUd?L4GONlyq1<@tt(c$ zW+((i;q7sR>Y<;ale;9ZsxX{_-#*px3@HA^H@Jr%c70hQezqnt_aHtf8!?AMQrTmU~S#`tHR{D7jjM(3s(PG7W>C7A14GS zX9T{u0hPn1)%Vm+gGh$k`;8NS@w=I+*XYS$cQ)760?yS&cOJL#cb%H|5hv?zB4$V`qK@%^o0P{KmeLR41pc3 zmI?_jr>|$nljNtLRMx5yJE6K8gT(Z~=S!3c_;HCKp>mX7$9L)Y$LL|jB>dUXamjU;ONIEE9S;)dd5Bkj|Cv*XrYJ(E6wR$`|rBD zbho6h*)M5E2Wqja9sae*C`5K2LY!lM_0*xYAY-BvIlQ1|Hqyw~P)NKqTViIz#WG3F z>r$`!=+OCv@eGNj+pv^QlKvvHEJ zNzOylpQp*{Xav2LPx(f&;h(e2D(=gmRb65K*Wlz87AiRnIoD}KkW3p7I-it)$tfvc zRsJ8<=PBG-WSedoL31dK@P8#)dk;BLsDeaGj^*9cHQx5%#M+{pU32oVPo1LlyAPA zU=U$TWQsSjMsXxMr;bTkz(Z^C0SinRH<&vAeRi-6m0;ilXoFrWc6V!IW&2|=94Jh3 zxSGX@ygHr>)!kS?j_?@#Cu}GaSJk#6)>>xMCiu6`{cZ(ny6`2XXx_5u;+}n(iR6#^ zBakYnyIC58F+MH5Rb9>hM~NOcEtP1EHE+65*L5;fR6NN{)1 z?&Dp&pG3RohdG+sYCpIeXTM}Pao$-Niw|aCJ z1e5&(()koZC!|yxh49ek_eO;xcf}v7(F4xh>u}~(kne&3WP+VQ9UyfP`Exq*X{&Xb zbhkI6gLdXzec%REcVl2DWD+x+kL-y}Qi(abA4TejR<0ygZ$y6h7NYI>C80*{i0PNx zmewz(jw3eLR&m1ZvrW^=<*@i1Z%4OGdu;B8^})dTlcxJ)B05#YNx9laypP`_g4=xzWneVjca8~b@G*ToMg8X z_jQlg+jvl-TiD9>X!AI4fOO+&d$XSE+0rldo_blVdjD^mM2-o!`}9PUQbjoVuNI|T zjRx8%uKqfNWd5BAKK>c&hwDCyAizS{&Xz$sB8SwbSwVr7w!Er?r&~FgW^9)uz-@=Q z%%-B*{7#M>G0>}wRRCQDtovZRb8r=4g#o1NUqcVbZtIpVG#oq8w5}M&UX>c*$x*Dx zgWrAap#M=L!5o~ID_>dmJ)o1fqrog`;$$bhPY_wo?CkXV56i?$@9_(X*<&-_Vxg(E zT_&`TjFgH+db5XI$%EvhDv?7T;vSrN0X?dFyKjvPnm$JC{n1tw^wq;`b=%7t3nUs_ z->2`J?#+$CK$Nkmm?VB_`-FM#ox9(!PThyr=<)48WL|kh(vhAEWny)D{1$W1S)@H` zlZ*%a_&ne&10f#)!QdMDK-kkARWBkb7Ei{K<&!Z-9?GU61V;GX*DfH37)mgD=!jsy z^WI|_ocFV)P8seOjF%C|hxICKZ)ZPna1iuF*nan1U@X#Ng0XUIB0`@YCa)@DN{wwU z+q=)2*J%IU^Ir0&{qEFcBM!WvZ=$s&_e@@wFP3;!8`m5E)!R5b-|Ro2zFiX0+U?Jg z>k%iLXv+$ZA$;3#7U__0hX9Bhf)Wt7VDPH`@cxS=YW5`2&)m;a2UW-aGq9xN;oIHH zl8n&j&ehlkv4h^Lq}H~ILTZbuS`nXqqMVE2Vwy-yO*TKu-jIwAM_70rO_bMQ#Wt3? zm$7aZr_H&I{fmlAtUxs2p$gB3#9X#HA|lbX^3bV<-FsM8F>%nKPa+A5W0Y$he?~&Nm?5N^n ztJLlz;i;=t;>tZZ58Cq@SH@H*s>>_(dowo>B0z@0>{RkuX)L9{nmD)xy+?L4OVQ#p zr^m~;tSoiYs3iiJxGH|sMNL1CmjXVTd_UREnj?GHiu}^zKH0z`il495w#?|3Y;)1`U*9_;;)*6JuYV ziOCtE(m9!BxmkpUG0uOZyHZ2h^DJD|POar}57(6qKwD z@-5%2?o5TCHj9B5Poer7gMNV1fBi$I;L@LnN-czZ$s8XOZEcT|+0sI-Bp$U(b(ukN zi>bVyu;4hSPdSK!n7dh3&5K<>;4w9g=(vmUSD#j~S8wTc8Jz1qzUSXk!S>AL%^k?ws*wUHi@xgPE*yp8p3 z*ny$yJ`uI!MfP@iF!yj<|0kPqBWXyW*mKTQLcGAuq~G3o*{YPp$DK5#3Sl0ypJb(n zxVZr#AwoE-@F7i0F=6pWN{siY$%bzcINeh;ip}HFbDFE0@1V7O8 zdp72ZS#2}7>5?eig4 zxYJTUkfi;ZQovR{gn0+b?dsoY7jyF*Jo`Yv1qt?-(tO z;!1uQ5yaYv)4-4obztNLRD{ytg#LSn!0{S@IZ(hvk%ig2X-@5$jHG?HFezuCwh`oW zHwMPQ|M}mQ=J_6?s>V+i!2~B*npsdp^OoGKtPW~~*FGVd(qb!XCw>sSUBOZ%{Cdcc zsrzjrWTT={whZ1_Lb(7KXr~5w?D@YspETZ-O1{L!kX_vdmbYN#L z*RX3fH~uj^m}JS2XujRNsDd?#>!&BNU2cW zje&4<^F1$;q7f>?Vv|+_J--L4iEc=a01*STG}2~&P2KUf>8$tMp7-a-HE%h}P%cU` zF+FU3KGZG^c00}GiK(q1_Pf27j#7-t*}Jgs_t5i`jtVy$`n=a$E`Oga)gB(;-}P*J zbABKCVQ|HFBZKv*M|Ot4wvO>S1)1PWGvViOO8>n-&@K|#NrG7d4IVFZeuSmk^BC4)=&ew?Q!kTq@Z}WBL2)Q)Ddd6+ER;4lO)dz1j n{y1t;?l!!uT?;~XZA literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00manifest.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/00manifest.i new file mode 100644 index 0000000000000000000000000000000000000000..52e266930adea1381d84a3e80669bd8f848ae3b6 GIT binary patch literal 21201 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_l_i_c_e_n_s_e.txt.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_l_i_c_e_n_s_e.txt.i new file mode 100644 index 0000000000000000000000000000000000000000..e4f64d39b78846e1144c276c29df9e6923a8b240 GIT binary patch literal 965 zcmZQzWME_f17=GG2G;iwHiO@PDEMd4rkt1LRBM~iachFGnI}W*cV?&>FjX;UYLIXK zV>5xhpTl{+ZDAByFD$}(YhFg@HqH}^yn;Ud(ugi`3K8P<@|#e9U((X?j?RYeIF_!% z=I@h_{W`X_^uB}CF1;@sxF-CrUGrEwIn!dV+y5UXhpvBNd-wdaect=$<>ecCO8@ic zoLiS0+mgTF*0Ha@i))U2K6P~6JHa)vuU{QJ_&3LHHgmqezp22lvVXVV-hCgE|Hr^> zzkR=4rRO2Z`M>4b3i{a1@4l(+_j(|aWUlhz(Q$Q-iKPoay4SDZoZ%oVJ7>bx{>9l3 zL=GEAWhKo|VZpl?d%sR2ml|$CrZAS8a|4@3l(NgXH(=m@rA4UcmZcX0mF6kif&&e!}7$Ef=Fzo{Cm)~a zd(557)XDvPBCmS+0#(Ne$Hnv~UR%6h=afMV%k8Zu30E%V?G$Tx9<-W$W+#uB^@eQ5 zm0IOd>#m7i(>mW`cA%RlpL_MwMVq+v_Z2js(C^{ebEEM`Tvj5F25(XDGojguo zy&kqK^qlFGsd`fddva1QEwP*~J@M=WSxHBmjzdk6pKbm>3CiVO==rN&M~~&SYW$N& zPAzK2D_yfro;|L4^g%$}yar8It(OY>xW63ws&{Z6Pqoy?^49(h9Fq4xh(`VX)$LNC zlDYI~o62fcbU(GHu%wk{&0MVelH%;;d fC*Oh8j}N{i8_sYEQZrh^U<*|Pqhx@LN)QJC*5|9d literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/_makefile.i new file mode 100644 index 0000000000000000000000000000000000000000..916236752f9e59f0595fa8d2a9a05e41770f4aeb GIT binary patch literal 1364 zcmZQzWME_f14d^C2Btp{HUqxAV^4;OVixH}vVww$xd6XQ#hR=88W3m6cDf^THt}qe&}@ z^G_SRzYrE<&ROzSRIntMT}<|t^eL8oGEJHb?6ld>RcH&eOyo$E)>^uA;Z+UA{D#A) zUzWam)h6J=S}qkGJy3E_LqNP#>Rf=O?Wpl6YvwrKXx4-~S~}m)-oP zcw0f34&R?9PwBONueVDk&v`NPuIAfU23wcraZH?`;PuJ$UJ%?;*_iTp?E>>D!c4?6A?DsclDrP1O+}2Xal3*8<@qwzyhK{u`v7MiVF=d&U{|% zKChqqk>qT}{fPlkH8AQ9&;(F4%4g;!=ai{^hiK{-7bWZaCT6GV0j0P= z>KXIEx>SHxtpc+c7(_wBAghAK95=5!Q*h(Hp3INkH)7uGFq}Ubss>6idI6QDLO6^c zfM#$)*i79(_F|Y?#z|n76i{qER7?U$GlA^b#=JhEO4(Q}@rmA>%oz*b+S!*~fa!zK zAg?fj+{(w93v{_cW?pegVonak^=rUtk{KA7VJ@=-iZFvruDx@;rETMf8+=K98)sb5 zKU-FIU&I$ks-Ow;oK9E)+b-)Ji5fhYHHeg=g6Co)-!t^O*%41MsG$) z9-rRIJ(ps5G#4CXSDbNBy8Gct%axs#H+tMAI+#f)9XxR03DZFyxrm;#+GqWarfF@m z*t9UAkiq<*cMr%SCVmjfs0d`Kf>=P{2gEEOC&mhuE;0P0*jHWIvftWf+MZX6&dW62aSF99{e6%6a z$)Gn@hVxX)tqeXHgILv~*9qKz_H*?1J*@4?4{yxpI_09Y(sxI}j-VKWMHKSPv%^ox97O7jNZ-v*@qUGAAWT>>zaJJSm_y1I58W5 zLkpOqn0TS#<`1M=*#vAt{t=YsuKf(s8lc2bc^Th?+Jss>6i)&V1D5s<^fnVgt<8 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl.go.i new file mode 100644 index 0000000000000000000000000000000000000000..f2ebe146cb115c06190338861ea415db726ba378 GIT binary patch literal 7624 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgl__test.go.i new file mode 100644 index 0000000000000000000000000000000000000000..a6698c8f42bb7f3060fb144238f91571442053d0 GIT binary patch literal 9376 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 AegFUf literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb.go.i new file mode 100644 index 0000000000000000000000000000000000000000..a20625e37396c7ba8ea54826fad9ab554a3f1a20 GIT binary patch literal 1936 zcmV;B2XFWQ0RRC20000000&S201&hQ00000002(^|NsC0|Ns9n1E?>=JG^6=!6b7z zn9we!acO%100000000000001ZoRwE?Z>z=<{tUlj8mXxr5hv%Ux>9r74+ImN$^jSf zNu#6c3d7o=!K?*1QFN65-e-2fCa2D6Z$3D%GxN+dFFVU#oS84BbWEMMhm!j={#m7pyg=S?Fr+E(%j0cO-ZBn^H9 ztcyZE=jEDGS!OvK)ocVD(OmtFN=u z111-;A_-ANo1_s{o)q;Vzp5I_u1B83@kOp|SXL$*!BqA=SIUDxWjb$aCaMu+Rm0T_ zEm0hF12{_(Wrk&-RP1{r8$mi1Fw8*e32G|{RQ^%8RrAap!Sv*=F^zgFQtlR5<-mBZ zxKB#mF?HQ?j;CHkQE(IA*`Z5#o`=CFZ|sig`kvycOHMGq5537WrfD!6yJ1AOKgOyb zhu-xf4zO@yN3c9G4VKvcJ-NTnLpO>j2+6yh&pe<3KD7PVb0dp9-Jb z&AeMLhFTn0?A0{>Zb!il-MXPO#jAbo&Aj+tQMvJApPk*nn@w{&j6G*DvqPFM!g&w@ ziz6F*ku$TsTX#HyfA}Q#lk3M6P3_t2t3ZQ0-wm1kn<%e=H1q81nX6qP&aoG|PRs!v zo*X0(1ZNgSbJy|s!TsGuGZBE?RgGXdB z?uALdJDGVC*LPf&1`KoOMedLb=0&XGX~%aqye>FwRVeV%kG;;dR5{7JA$$DEW8$16 z) za*e%k(qP1#n8R;@{u*4r3kb3EAks%#?aEZ06wS+4j7JR|&Rb<;={$2}hmVxZC<+kDlL zR04C95-P$4j4A-Fz>5RF61Wu)0RnjS5zvNkKr?p=@ zp9(5psi_N}^pMm%R+s9~K7HLvR76}tpPTz9-A0zsdSh%yBy^injh@D@H*Yo(-u{S_Fg+VVZftN zjR7}&x3h5Q)T&eE79rYMM!!%lo1|SBi-MmbQ9X$&YUEb;FzE$-WFh2Uf7D9iw1PvY z$gRVl5qXKjD5=&p+6K>vDM`hbu1qa#53XG~;2oR>vN;-Q( z1C5xckAT@1i{Cn*O;T~;Q~k}?2GAB?2{nfS8m?sn8g=!=RXx=!Tt6murI|g7!B_N# z_$uibUTKXZJe8KF3M54pyF#-ad=NjeoI3)o0{^2WrWL*m2E#*>V0j;w+^TMW6VHHo zw_yyG4#LvmjJgE=d`_otXnpB7fJJ3qboJtXNz{JAUit@T(B=Jo*iHY!t!_z+J#;R| zdPixm?HA8C{c3|ZqvhZFhN(q)*0~OKj+MV1w&PP?%bw4)m)N~nb*Lp_|Gc>IOlA;F4T!FoQ#-*h z|B!(|>+@gXHkz`h9GZ5OCM?MGn7CkKL!M4wv4r+H$(wvZ|7v;P-g*1Zwzk|~|M10< z6xDK#y9O3+Z#S5(onCiHW@))hsEI2H_ohvgnFD+&nu zms=TsX%_TfxeTfXMri^W2|#SFtl*qqP+63jo>8J;WMF8Z;8v8Fm#yGinwpc7TBM+_ z;GdI{nwL~sln!LOrxxWV=2hw`Z~<*&2VzU05!xY+LGHFCnJK9`iFqly$>}+I>G}ET zIjPC{DXDtN`MLTT>H0v?LE}m8;~QPnU|bXnv$xZqT%iz^Z! ztScL+<&n_dFEx4-1T7uraGNxF&g5oDP*ErY007P- A_W%F@ literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb.go.i new file mode 100644 index 0000000000000000000000000000000000000000..d2535e3c4f029d5c2ca4cf421071f16253e50a19 GIT binary patch literal 3519 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 F|37d~dR+hj literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglctb/cglctb__test.go.i new file mode 100644 index 0000000000000000000000000000000000000000..ff6f1571dad25b946c986b739524062fb38a59be GIT binary patch literal 2261 zcmYjS2{aUJ7oJR`vhUS5%nT}7$Dm}*l8KNdG)5RR#tf0kO!lpzkU}KN*k*`9){rcJ zmQeVtQ;aoaNtT3A@zMW%=k%QOF88_jocF%>p7(tK2LJ~EzX9q40C>FrzXt$z|HXsE zqD+zME~<#s42{c_k>&t6^W(pm{nekAd)1MgW+xDG*SU=G#P!6{kU#-h+e5`?;T25BG zYt5jY{77bpNBX1hD|~p#By`_bjM}k>j-JKB*zY@Yj$vy~VAp_An=S0{G^{bWseGXqg8^t2z15br!29^w6}1g!2qL>iaua#V7ARWXQ9o?%HX3dz@k;Ep2)8 zgV0&$<~T`qCpvgKqOB1d=rf6E*@@KK1B#uG2Ya>|q>h<5E$Tee3-{ML^4W;u$~(cS z;z?cE;W*}k#H_!R)IDm&W*?tp(=P=crIta7{&~?i!YMS2ujsvRCT2;m!L=?Is?N6- zK%*upkVB}sK|yV;XN_7_VMa@{_H#%Gkto^_ z>OveLmZ=2+KvSokUWS_Wwrtc9VmMP8z$#lZ_8C%%GGDHAdu1ogq9Tih$p-O$d@Vrz zZaQ&Blj=RvtyEstEYGcvaOODg6PDS`RjXE&x1mwKuoEknAFIkgDx1Xjx0&?QOk`Q~ zY?R^4;F6j>(7d%zf+QQL;t-t2Ag^IvA8#r~I*$ULbP=4En zNR{@{yUQqf@l8#KXpzXP;>q|PQ0bh{Bv#_q#x3kkVg-+&D|ymT3uf?U6K1|TO17ZY zHcYMFcBZcMe<#1-}rIXpOEGJlF5K3`whsosqFJJFqCW{0e7$B*#>qq^K z$b|C#U<`!UoSc-S{+3G>Z=1v0x=R||ZG}FrNq(rmro*l3>}_+$uvty>K@qs~Dc?A@ z@5T5cYz{~)wf3+zhLlIxJdaxU((o+s3Q%pCsgl)nTRtOI2Cg@V;00KO6@nlupQ_B( zmz`Pk;hx^OA=pyy(f;t~WW|0kw&K?@)0DNZNlx>RKl3TIV+5uc7ae){AzfmemXe4B zu}h+wiDkpt7O51!2!z{Eo(09sdmP(6k$dE_n3I-<28uTGNzA2GoBdn`9g)8dOVn;N zns@0`5suy2l!vFmrDNl6rcVS$E$9?yUgRf&aTmF!5v3=s5u`vbd7W>3?rE(N%%u3F zZTF=v+)@Bid#pormEktQWR(v;sl2TmAPKK$?kZ@BeX@`DJ&^4aG+pY3!pa|9`y{bY z@`D~<8Ol*jiD8hBjCpq2vG?Aibt!vvEKd69l}wFXxgY1^`>yM@ZXDjOP3DS$R;NZh zD)dMhit|o+?$i<_bRBx>D&I}EvsbTW#prTKJ#kGuU`=kd8Rz`I{M8%D0O?Oi+>}}H z`+|p6o4lNGt*YW1_67MS1?dtLb_dN)sI78|603P1@Z=Vpv_z5^v~L|QU0xJEeQegB zLQy!shGyhjr7cyTTUZK6UPFEVz~6hrL8JvCxO0AaxhpPap^Fs#zq2~x=21eUliPS9 z?-%x6B`1zNO`BF6OWqV-c9%)G3(gudy_wK)oAc)c%e^uvE5kfqI+WN@r|UP^$F=~o zby(VZ?480|oj{<9_QeKd*k)r}K-B8=kQX?6JUf$pACif+li0<*Jm*I$`UzaUTmNwX zSKrqH0N?;_PZ56Gdj`)wvo8wKqCRketBVe{TN>xXmt>0<@+1THegDCq7Lw3?saa2; z^?Q!zg1JB)F9^Xjc@-0AIoHULqT5*t@Xxy?BCBdo)>azJI)(6oN_3<7KQ9<2zv zVKpufT{$1MiT_ryjSRN(Y1eQzrbD(UzC{+M3))_%4vdT?v(1eFh=&5TEs!#}o38CN zyk&uo#ib8EbB(C=iMFzkjH^TGfw9{8tOwU8-IzNt-Q6qdKO(Q?rw!z7nZE_4Xo&kt zLa*D$A6~5aagWOHG=5A}Pa-7M;LeR}?l6{*>cW=85lXEdcTY;TVX76QGSZmo-=6YV zl}1Z#_~1iyB$frfmh)V6CE`WHJAtH{@lD_hmq5+^QXe|=yWo^RS|qc_9N2G>al)25 zSL%*0BlPpjEb4%w^KlE;-_ie0{xlp0(}Trej1OTQF3N#rK#aSHeW$~Xv?9+y3^ zHw&oQ8MiZTQ*oE|k#vss6OKS>M?;_zz`sU3bpPl>%-;zp{E@TV9>cMpGwI{x+0R^W zUVWj~eEkSeTEDiLynmlRLEJN<_Xg~UHQp2NLdL@oO3F&gFnv!F(FLZWj6f(Vt0*E= Gxc&hnaT3b_ literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgldoc/_l_i_c_e_n_s_e.txt.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgldoc/_l_i_c_e_n_s_e.txt.i new file mode 100644 index 0000000000000000000000000000000000000000..a63c1e83567f5616246e4a7d1db01dc17b897b23 GIT binary patch literal 856 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 C;V%II literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cgleca__test.go.i new file mode 100644 index 0000000000000000000000000000000000000000..4a33e6d55cdb5b16346806ab018687578c06f2aa GIT binary patch literal 10665 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 CPjfZ^ literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecauep.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cgleca/cglecauep.go.i new file mode 100644 index 0000000000000000000000000000000000000000..61381978bebc37603d630903bf1ef3d78f17cd9b GIT binary patch literal 4488 zcmXw*WmFXE*Tv}&7z75Skxr$h1_V*KbPLFUNXHOEx1e+h5`%PicQXtU5)wm~Lku7Y z3>^}$-v52~TF*IWt!IBYUw-RsENm=ntbawUfQ7~3^uHMk>;6B9>;}fy$R9Wod`OSL zb&Wm4{e;5(f6w3Uli6kbPHSV7;*Rk?ns>_off!!3i+@V>p@B#gwi=hF)3&7k*~hxM zUc`}-BcYiey2smQ&Wp5;NnMA1<(-#zwy%v>_KL8S)D(dkWBpex#Wc)Jbct(kZ?sF8 zU^a?2mN0c|(7hKo)f(C!N~}gX@yhklw!o0Yhu*qpMpgog91g<3n6@D?C!w`HZVJIe zH(E`=npR1U)*ATor!3g%VI;96whXbcUk8O+K)1OCxIFlk53Mp3 zm4qe=Ahn2#-vHUNR^q>h$A%{SxRSaXoRC(zWXEU0h{b;6VQ2sP?rM&Sj}BA1`4E%P z>yU(gY;?dbfjDuw!qrImqT1wys?0g1^#Q`#`qD<7h!CMRL$K_;R`*67k{=P5Z^_uH1 z_Fq=x3f-LjMBTjNS3T19;%zl)QV-w(Yokt&>UiqQergJ=bcz&Po_><+y>uQ0xe9uY z_)(Vz%8D|w-LnmgzN}Zj9TiFDk9BvD9{5@i+^j{V&P>^;g!&#Ar9wVHj$1I9l|k`g zebQnayum^O4r>sasW~Nyb#CS6Zxu`mvjkJv{{}O(#)!^|c7@r(!<@9N>rMNvoHa== zT+A1$)#nl7N;?STH}QAo&93x0<22POzJ2=Rpgt&#`*@>mMC-_08eOcZ@>1Dot!&by z#b?NNxHd1D8?KUTpgl_R;6$BZOG>(^x4%)N^IG~e()iTj9b&Y#c9g{OnXug~SDGVI z9AMw44tt$8eAEbeh-4XS%L122%qS#bdVT zKaVdqgys;1moQx>)GNb{&8OztxA+$eu}9}O;yYNSbpT4iCFEZN0^$e(R1vO?BV;O^ zm@@_`I`+kfPm~e{z7YWcO1Y6M_sVyqiJ$$3k46U|0F2UNBv5W2eiy4K7W6b9IxQmY zzEN8!r#{~vGQpa*hN&eAo~M>`J(C1@V;@bm!7d01E>Yb6ld^5A0;vVujW@@(ZlSF` zK~l0|v6Dq9y%H#1To4?MZ#;2%M)Lcn&0HsUo$TRN28W@4BTW8CQeVc8qa^M$gfn0a zV8EEjQkygG<|yP~z@g7Fi9zM`fNm-(^==31&wgTH5sHhvUvhL5EDoM?E|WX@pIUSh z!N;!Na6wC|-z+2%bM0@t!&1TRBBbyW!tpw}ayOk;Vq96C185nyc!%S89%K%T)}UE@$XU^s!;kE+E}1i#IjQpaZ@XHJg$>7(GymSDBG_EQ45y{-yVu zuWSeObgiQ(>q=j4-`t6fyTgp{$6=}Ip=XYu#Hq&h>R~%@)CRmq%r(?j! z;e%s(O<^&-y@<>1FhhG$jLT28vai?7De6L{qR(1T1Kn*@pV`j9mS1mN{=kvJ%Uj=PBKRtQYp8A5ob?rNXL{wX$lgMe*F=EH#_rG6j_cXX@@BiU==0CvyBhp9 z7SqYuOu@6^o-vogFGdTIyNX~hzxk^1`?4^ng4N2`uhh9JAvP^o(<99``K!atPs%+6 zR!$x4mL5NE&vCjq!QTHB-+Cdv&k1ev_1T^^F}?zCcC-h#e7vlF^1j>T(qGXh>86Gz z)pk8&?~~kO58{qfiTY->c*#Kl=0H;P%no9(*0NX8-~ZZ_C;b_{__sy@g*NUjU%NN#LICu8|5wul|Ia)bi=bn?D@ilR7=R3mx$umYK52JFdvsEh85 z5iGDrx2Zq$18qs;3;E1?h=LJyyS$P%v2!m;`HT3|g8^x;$q#VY73Vi&Saw z2fbW!(~)^;lB#bySmrSqn7hSsOq1J;D}Lyk>-Bqn$#(P5zv=LNv1anmSw#V6ryV;b zUk)mkn_QVuB&<4!+(p;WpWf<}?S5W1mp@7_x*Bw;Wi}M~k)QnFsWzX2L;)j}Y7yqi zgQ8}6ZR6^NN5Yc~iQuP4`RL0tx^r(yP9j7?eZ<(C#U8*$Q=sp&gTDKH@t`3Vq$&Ae z7IX9iAL8T_<+mu=8yButoWh>IX(3@Ty7w$vA8pNv!y6puvTy@tlJ9rol4w`!P-fA^ zLfjvgo-Ei@7PjNR_wCXdax{q5&&t{5J|Cw?l=d?Z_J>nc=sNpEtB8}%&Act}+PP^i zIypZ6rL|pjOT@;4?1<3%(G%~xm2L?&0F0sBNTr_)ZgfZg@yYT3yWRu z@AOCihOECC>?^?Hc8FvpoRV)<#t&$p86wd{{y)qAs!wK>frjI>HgN341gSxJ^P9TG zCBcj`qz7MQk#3!S*o&D(ambjyHJ<99 zQ`%UvkMEjcyW~}yehRI8C3hCG+rfP9b`ioo-@!Mhs6cYyuoJ~=(jKCf8B=GHhnYDy zK>|!LoEv=lPo63+qVJ{)67f1Do}lL*GTski=fauv+C~Y*=bLOO{0UlaxiEm`$FuZx z)AJVZU#jx+k*H85Jr1=g1PzKTJ;(m>@Vc=(MO9t1DbD_RNY8?)%r)a>a90B#lA*fg z36f9&KDzN%tZD<0#sJL*Y}1`waBI!6UWzfHDT$94y?U9{;18@$A^XJc?G{(v7#r0p zU+;ARPt6c%pjKg{)rkBHc~+fB^0dsCyzK+;j!UgE>8Zby98#Fvl#xj#t22Np)VbFR zj%tT$(;j;`Dy}&DfFEw!nK=bRXupgi)^T^}z(v)ujS)D?B+B9T$nP5B$GU&A{C??G zcxUx^4iZ%;wy!SeDwPzZVKrfhohnot*KMS*#us9!dg2ejS z3${1p*<@9rccKULHo3S9H_(gp;`HFWe>@T6+qdx2l!d9NF!6(wO?*tK6eKzHyOypU z-*>)d(RF9f)Q$6ep)T0Nmd_L|D*Di*sG)cn1eE$uWQy7082t4d8?`&>yyrLHiqLLw z|FY4T_(13J*;=xOrz$02wjdoPcOi&Nz9#+SrmI*(*H&0v)8gI{B@?@KUa8D9l*~MM zTwa&UA}J6dg5Siv-k2NmELV*fG2`-dh|>9C_w{}~H^lKvdW2KE&P`tLb;82jLtqWs z-S6N&=ji#PoEqd`$VhYlR$K!tEH>M}(;wmedDwsPG_UcrBFzr#|EhedB~(1m1&{uT z`PcDZ@yU!c7*O|85N@`Pv=v!9ZK6n3%0z2}(o_A5v~^LRl^nIpafh^ACMMgW6bu_A*v72nsIBjA@Cf2Z|u>5e+s7?N?LkN#DumB}r^| zF)5y=&AcrHdEzRc_0L&nI98fCJbl_Qv$^aHvG(8ae}Ac~yCphz9xG9ckl=ZW zFAm$AwkvjSdWOu-&r@#B=r6~y{#1g_7N8-?L4r0C8)Ni3x78OK4d6o%VEj8_0Q zc@}(O!DR~rymxcb})z9WaEe9)-GiD9(oWP?ZHJY*uQdQ7OzE^#j| zC+=Z0G;lpfv8%$PRARDnk>-12hIxIQ`Ghv79_*TXz~NKkHAMJD;=!8y6__GjcoDKX zf+!6dVd8pc!5meDuCHy{hLgMo^^&^czaT1Za5W}PGabe2udX__NsXRVd~3$htBB$i zxDQ8z!mFmytNqvhh+_tvl%m%4V1Gk*iDJiil|jWBTSx|$1!?iQCL!M*GG$*m8_@ooX!glL#`^4B^y1s?guo2NI^1* zF@IFsa8Q=}8+eaGMq`gy042V{z$3k}Ix54|>ReSa`I2NP z3yrFMjLo=tE{z5s3sH~k;p<^UX zk!+h`afD3#7`Fe<^KbLXv@|zQ`v!;CQbkfre$;i>rHav`COsoPB?U6NKMHo+b|{i`2UbF;-HwrGH@YL@$7*UGz~p2PAgNeLIgngbh({R5V8QJJ z5D#d*l~QQW^NPD_gtaCj-I_sJ0a9zu5oh%HqrU5PVYk$X zw~T(gnpt*-W^t_(?4|7FO@xTQ^iX3-R2u{>mZ6_y3B_VOTZ;Uu2TRECQSS%dm68YB z5_3hS=g;;UO*lkslN&SRkTr%J$QIU3MO5p(84j__PSNv$6^aiWE9D1Xz?*R&LV|pc zFf4ES#EsV+G5RNclHPnb9r}~uitO%=Hyn<`atgQ042@;%%#y7V17uSCZzsZP4KLd) z0AQb+-i!(v^0v1pe054)K}Q|Crz!Oz?~V)P=tBEp^nn@?;fs1&ea#2POl$onYx{iXDQlt$CyrnW1DaYCr%2+uGwz}U+eb^lgbO9HREj2-` z7z3Tq>Aq%0;3B7-YV7pAWap?KdaUBW8VVI*f#s{Q_JU430m+PG_tkubAZQo4o~O$o zMup*A2>%q$5o4X`$zPNuF_K*MCDkvdOVOcb@Z{R@T-1eq`E%DZ;8O5vC}=ik9E+i4 zI0FXYMq~EpkJPt9V{%q#9WRD*^2D};$^w;{vd9#2!(}wXQ=PPazpkAcU3$Hq5~|Ae zp^D~Pi!zg~uxrYl9Uxvg2uTux<>hmXwc&!)Up#w=F)hdE^9DB}_D|+iTBa5D+L%G9 zVvSx9$13YQvRuv2k=>WH4aV4N)vp((mU~0IMtG+7aO2wm(3{mTpIAQX@KC8K#)&fs zA}p}w${Mpcv(1_FqAR$I>>pmt?WeY8&av9weisv+G#+r;emZ_vuHpActmy=YHz(vb zuR25RMD70W9SxFFJHzDLJIC3ffzzMrx!O;J=;nN`DI(T`l{EtwPe8L3tmi2-5A*1_ zX^prqyjTr-V!1PCZ3*d`K(q&I|)z`fi=Wlmbbk_1>PB&1ASGfOk;U^%B*!wD99!->-J-}Lbb(A#1p90-ZAq!&-VFPjr{1Lew~`3 zWm%V8P1(ReJU@uZUz9(3QIKB0LO~Z*WPghQ?Yl6uB(9yd)H(x+|9tP&hMy0`2f__q zPPVrVvWAoBfo?&q+TG8C?zqp|KCe=#*OoeagUQ@-zdJz zs_%<*!1nLJhs=U<`&aXcMZ?;v90C3PknsXmA01Z z>a5Y(kIL8(X}{GlQjkT_7*07v0_kw61)g9|v!yb9uvlE4@XatMLh?1cn)3U5wTd?H zwgD<=t+Xdzq9an^0+`aSKb6NfxYFBvDf_H}5sObwGxZ6QHpTQQRwmcRWywOn;Aca(26>(`UZgZ9bu9+CZ3)wbMv zY~};?#3+Z?XQ}0PwD8%t&=R*ivUq#Q1o(KXk>bPAQ)v?8@S1_~M6+4NO-2bMv-D&s zSbh*(Eu*mxVaU_wH#pxw(%b_zCO8pi`N!fadPFh%YnKARX&X=H!-XAIc27V;l(mq8 zf^_@ry8Y}9a9RDrgnKK@d-``Y2^TOu3+kqI<+Yb#BYxgMA6yl~-_A`76st?NGx_5Cdic7% zd{YAq`hII~$fWuhBE??Ah$&Pxk5IbFuuW*w;LMl{BeJ{<^|d{qu4baQpcsFgB4C+u zq+v07*}#H+`QVnI6VdeByIbp4m!$Ow846os!Uhtn9#PlCEFhlfd^>LM`=;+$M~W5} zM3$_OB-#!OfMBb3?~%x9bVdgnrSz>+#wPU&eIJ2pj(2@ah|4nxJ9cSGwZ-CX{&p8l zTDA<&uMc?&)Qk(rZDmmEwrgZcnpCkz-Ohw8e$gV%eroMoQuGSpP9rHyKyTSr-*^=I`;582+u^MBcVjzzU6eDugWl&Ada%qxjyRd&rDHG*A zjEcrxBNFB|_B8_{p7dm2nR$|~jM;q*CN)d5`gis9Th-XxY{wJv*%zO+F*l0L(3zjT zyf=r0&QQzmpBhG~a8@Kcc7E?^5^6}I&vNvKCtYQW)*k?Iq=owqNzg+>y6c-hlBMeP zJ!~UU^MV@MM`lt&b=8wV0Wq~L_D(=Rz?wpFb#jdQJHO#L&*$mvF3(uJtrvGm?_}yW zfrq!+wjQ$1@T?vK%%~r*L1LoiShkLbS$hXGua&c*jP|W^BTL$slh1GVM3#5Pve2hx z>PL4hI%6E}^T-p$cMEi6$F)4%KRKg1HG@B|dt5I5wZCr=>%r4Oq_fXge&7j^?dh_? zzjy#gYeURBr=OREF?6NiW}nucW!1jof&czJ(r5VS6SRT_b_Q$kmzYScwJnEMj;M+C z=T^5VRHUY)&u?6w&+`kkE!HJWtB(Dw=V#|em5pH`XPBd(O3ITb-wqMhG{Ld``)-46 zr*YX$sGrKXs~f7tw@K0S^)A4@n}_R)F_G~=+knlRM;lfuJn*r4oE7DHM!2H!@9$dK z+v%~d6Ncwv;-MCrtu(Z($L%aL3sgXt*x{3INukHhno+cKAD&4wuTTCel9Q(?F<8& z)&!s>NaS}@s8?cUM%aq)G0e=h@ zzbFwpkoViSVN8$BNe=Cnz8`=?52p8IVdG=pES)8>L(?id9a~?w9VXgtB}iosV_b40 zg3k^3yq7(G9HD#cHq8b$y}{1!k<#pkHn;T$Sv3cmh(68MzgjyYDOT_mRe$E*pN$9r zP*ef{d~g4x|4R4I`7;*1G^FC3Qn|4ftF;xhBzMNO$<5q9zyAxF)os?U*Cll+v1g(- zn%3TC1n#uEheDbty#VvFY2xBshm0D!rzQpFVruLbi%%#bqFdJr$sa{G44)GC#?iqy z_n94bGNh01QJ*uh3(@3*zAy9cyq7V2gd^=&9?5Soa$>Tv?yP}1{$6`4a(%Q6opqEA zl$^IU7D$8Ejf~o^?L~CFMa*n0EN|PcI0+3FGV1~%9kci+WquU-P0zn=P10qj$%}nm zDNI!@*!P?cf&O8X*?Kv|HtbqLOcYx-_MKd`k7(8# zt!eMsA%5W-a>`c{h?XjaX_s za)bR<0V1&snts%0R^#K-16X+`(H<&%=|{oXY4J+bFY$UsFXzLRGDerrg(NK7w%QAW%*Zu0<8_X#Xv%Ya#|4Yua34P|@|}Z8 z&|h?n8GqsZ1OWK2{KKgCU#Iwk`tUA-h;u88;Gdq$6Yt{k7P2D}Fws|{EmB%k={XqZsB6_ZDI zB04!kT@u2b^O5(Bbj@5f`MCydy#*>T4cT%EDWB72@!zqMd&TC>h&t<0#p$$Y1W+rG zyZ8p5t4`s_%q;{HZyy**W~>OB;}Q&3N^Dmlk0|%HDB_Nks0OI?MgwOULLYM4@i#Ad z(R_`sTWziifjO3r@O4ZXGRvNr23k|Eyn+%WYU;a~iel4W-k;}1=1{J?aG!&M_iTcx qcpjN0l0a-+roHj4?4{l;cu7^Q>QaO3g1i(Lfr!XuJCA^vlK%iF(~8^x literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm.go.i new file mode 100644 index 0000000000000000000000000000000000000000..ed031df8a8c38c403a571257ccf00a52b3c95231 GIT binary patch literal 2731 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglfsm/cglfsm__test.go.i new file mode 100644 index 0000000000000000000000000000000000000000..a1cdebcf4f9846f58dbb18245f2c33e7cf22378f GIT binary patch literal 4254 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 MYv#V=1GvMKMw=kl$a^+zG=jd#3xT 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 F`ag<~z9#?x literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/_makefile.i new file mode 100644 index 0000000000000000000000000000000000000000..c25c7560dfc96941185af154bd050c1ce39fe246 GIT binary patch literal 910 zcmZQzWME_f14cy#2F586HUq+pFexuKWo97D=@5sLjDNm`-dU7ves7|D;SLtR zWzO0wo3~1{xd&L^m^n?=f5M@A6FK{MGbeVa%!^Ss`z4eRDWd;!Q-xl_;Yn3D`ZIKm zo?N)Ww^BCp_)a%D6<^6SC7HTswy?YP*BsVs_V0giPC)NibGfoM%Tucs4dq35d1r2D zE@R?ce|-Cu_LE8xizg^a>KQdmV$nTxv-gVYv4AatWw%Se7Or`aqm$+&5meSwFF*g) zvkNB6UEf7Mt-hIDw*A!MU$u%yR@z)y{o%I9sx4=?6yJJe8?@}sgx}In8{J=h-qBOa z8E8KH?K-P<`;Hv$Z%ypDGXKlHGoSXeT#xJCxoFkRjwjM;a~uAH0tpnfKwu7J^@3SI z28afQabsJ+LDus>i=E96ERhzoDr}CMCkIsnQ_2ri?g->)hd2hg+m>Xeq~;{%rRXN7 z=jf&9=cnhSCg-Q5>Lusr>Sv_u14VQ5^SD5I86&_ZbO2dTz$^v^7LYK=+S^^9WY-o} zpS_*Vta#HTBkK1uS0|_%FjX-pIU%9q_bxw1#dV6%WU?=ebSx><%1_luz%>?pCYDv2K|KB2l35UI1>+D{)xjNju3{?ZA z7#~CZ&!h|qm3Lr?1fb|gs1gkz%?vV)FYT&A`|1giJM)8rgKFB}*BU$OLDhgMaHw2J zOh`DvkR+YT`utDRsYPeL^a!ykGc$X~DlWKRz3{YzKo%(4loFo tTv}A3aNBmPhPmPTApgeh#zsTYCdmqm$(M_ZK7aml>2vZ9hInlWbpX{%Xj1?H literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon.go.i new file mode 100644 index 0000000000000000000000000000000000000000..ae5a274e67d0d312f14c6615b39f9744e6e5d88e GIT binary patch literal 1910 zcmV-+2Z{Iq0RRC20000000dV600@`>00000001ff|NsC0|Ns9AidDuju!nL7Wct+r00000000000001ZoRwBhZ{s!)JzKwGkW&))D|>5;J;)Mm6ObiWq>{~1 zk!XilNi-xXX;AdP_fdA@>{p8B5HOsX_uf2?$C+JwBdJSOq+PrXEM->P+7jYPfmO zjZ?NWZQYIOS=&c4tv9Mosdu`_UFDeaR?z{(+FDi8p*2tFu_XJLTl`X}t}644rl>GY zsa;X$ih!f+?>|WC$n0J<6sA;E_noCy*&Ny&UjAU7Tt$$o%$+G(buZ6gRR~OB{S2KL8zrV zx2n~7)t&tvUSp_xC*HLaD?QY>Sd-VvNqHN)#+(C#)7o}U=n=uR9jIRD0gr=efM!Fg zDRB*y)^XRyDmq$$!V;pMkhVi$@E;Giv(IiKoIKN8Z`2)B;id&u8W_*5o0H}^FPZ{C7O_N(5vXB<{B-f0BWP6|T)mqXzi9(hN^5YPE z$&xlK4c7S6U+{>_`$5W*%h-`E!RFJ}PbCks$WLjTrQ1XR%XJoV5kx-Uuy6`~a1y&^ zu_Uqfqv*Rvle?IuPW(4rE`Stqe-W`G75WT$$^z*cI-dfV2Z7O;#Fhoz9oQF!Zv6Cq z3{dQsBo^$?3|WX$=x_WLy1V=jSMV-Dma>f#oh-eP$QD9!nMp>gBnbzz1xs&vz{DRE zC1Nlv6Ko6$={stN0k;swd65b3e1p}oWNDghB~Rijyz(8KLGM0l!@=Ps9=e4|NqX;4 zoejeSjOlL8aF2J6hsI>;I~xRS3*`GeFv3Oou1$*BD&i{^2h2qi2Xn^-yK)c4h0EYa z;yWL#nQMD^DCjyK-%aj#cuwL=^21y1ggcL1Hby}3)3~5YWWoC6`P93fdERVBq2BFO ziv>XS+xGzN@?`H=^|Ubc>~TNC zZEvd!@9HDERg^3+eYddMjr6a1pYoQv9!uj%ci1A=NA#(9yBac-tp)zZ^1FUBO2Vhj zt4+t~5v|j&xz0DCEPr+El=YEKF_*v8y6c+)_G^22MSo)fo@IZglkQkOpQT?my27}f z#eb$oJ+luQxIAN`@Z8BzD1O?_Hzog|H~cfgFr65_e*xS`rZfNm000D6000000Z9M= z3NQcw0000005kvq00960|Nll}U1b6oFOc$7Jt*B{hoJ=I+n)dc0000000000004NL zb&=0b!axwl*Ne)Yd;&A+35;!lcp`crK!{PWDV$B#?X+Fp?l#*NV+@bz>v(oc5r}^# z`40P=Z)SIA2s!>B8<9@SDMf^msmSGt^b)NTiCjnMah>^T;#*o&xkCv#Ics#JeIJ71 z=x#Wjz<9D4g}1@-A*8-m8mEoXZ(dF=+U@R9D?RF z-Wl5+u&<~}>FpW3)0Szv{>s@@YsOR+Gj0uN1^~`-`%CB2Cg&_e3%|n|=`7Oz(84-riP1cIX%L&zX+^00005pa1{>009;N018R~00000002e+00061|NsAY#qSp! zb6RsFzPJOpAX5Mr-xvM>00000000000001ZoL!HxO2j}AhPP6aXRsIof`YjuY9%NL zXK{rf<_gy_ wPB`!yVdzS96FRs9i<`%pWz8s0GseMjei29B(_eeZXeEZ#4EAIE26xwb;Ccj-G5`Po literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmon__test.go.i new file mode 100644 index 0000000000000000000000000000000000000000..4e7260a6c1e3c2b9035ade1bfa6daf13875e590d GIT binary patch literal 2172 zcmXw3c{~&TA0D;kT7@a(&K+|`?zxkZD_3G+%#mxzDp%#0?{ZDCnVh*J#c1}EFjo^f zicCT?-!D=uQTq8dzkbi_^?9D>kLRDy^LoD?02hD@aDc=8003|G|2zP&{|Doa9x!I& zj}H1b&HYN`q75XGoJ!3%$kboq~_rqOf093 z#f|0PE^0k>7_WW5{{ao&T~RD1AG;?fI{M3y#dw9Y4Q{I3qOZ9WJ3F1Q4hivgDQa$L zrPOd?&FITxpQhhpuA(Bwe>gF>-^Z1dG3GsXzd2aWmDz5XY!tq{xxuLXOSR1pm898O zQirno3e|~EtZiy}NUT4soVV4VtmNB z+pOKKFe5bJeMww|7>nGPMY(t#gSJF64Xp{x*<1LSz|!&IF{!kzYAvz#hRqW=ozRGJ zkTmE`=M~HmmsXW)5715{=7Rym9F4L`w+Ly?@L{@BbnU5nIG+0y%l;ixy;$l~3lbj* zmnKu=OC(*Q(^+ld+u-AqvuiHOzF@z)9K+E}v&kbZYXEp8EK0H;wlBzCl7M6`JBiM= zKBXMBut8cYz(qtt0_u(DrY`;<&!LtcrUo144b6&@XCSUXl}#z;Zrr1$MT3?BY~8AGkO@A^?N+%*k{r*fwUFO1wrFf8iw$==uF)i9P!d9!U%PMrzVZQDSPAX5}<(uRgx#MKf0Q zGHj*~JiRuDC=a!+vK!gc+)GDMv#feP?)S&w;N|Rr@^cTkN3n3LGQ!w|YDxk?blXnd zN(Liq%KzjmzQHtq@fP;9LXuw(zdLaUoy-?Mm+S;gUQox&l%}Uh49X6kSNK*QN{LoGX4{A7jHk*?R9#)pGO%Ze$uKAsc95q8ary! z)Ok_gZ#;~o^3KRdsL4ni?7Q2mm!mCOyMgJzv}m015pSB9IRQ>OD(NFCmaJbL5yg&W ze7L;Z<`fwid<1R$VMkO&3aVD`5H~ATGka&Q)ikG&5b7|O{@Rfzono6zd7Y`D7N$zN zb`cwDdNk^@i=%Y%=?&qofP)1RMbxEo;lJ7tXB&IN}*TaR}~ zeoIRlG)#QD=KQ30+K06*=&3&{leWZo`7G>j+-kzQqZUN(=BDMIM>~-E@e}+%2-5mQ z1jyQB zF!qdr-){j+=~Wed6&HY4fb)A)dj4Joof<2n1Q~Sau~UbtEOYGfJyKMYI2K2H*zhW zf@OnFDg{S{+IjjrhSb{xWo26kj>X-0h*1dY$B5g2KDWIml)Vy%JbJ6o9ytdWGG(m>cg&l zQy%pGMY>TFFbBQI?ems;Wf74i>^=puvAsHae!)*RBa|I*PctJ!=kTEwB`^C%Q%-T9 zu7mo1Gr!HBB00*hY5ga2AP09>`}_2Yxcc}==5+>j zSXv!l`VG(x5MQV)fD|d9ejfn=34fRb&~0_-Z+8P&hG$ZK+ELQkv_2bm?;2w Q`LK62fD8siE?O4<3u*V@t^fc4 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonetm.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmon/cglmonetm.go.i new file mode 100644 index 0000000000000000000000000000000000000000..83eda898fb4fe0cf1c5b1d840e2e7b866040644e GIT binary patch literal 5188 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmrp.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglmrp.go.i new file mode 100644 index 0000000000000000000000000000000000000000..29b6a67cedf79f6d1ac0b7108845b24f05ec806d GIT binary patch literal 2370 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 HoFk72h)&ny literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/_makefile.i new file mode 100644 index 0000000000000000000000000000000000000000..d32941a4c4606276d412ff887c8c3c6884372fac GIT binary patch literal 400 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumgra.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumgra.go.i new file mode 100644 index 0000000000000000000000000000000000000000..478f92f99db7c4eb860f06f2cf08125c3d29bfb1 GIT binary patch literal 2326 zcmV+x3F-C#0RRC20000000`Cq02(y_00000001HX|NsC0|NsA}R!Y*oJaRWU_(Ghb zeUOjg#iQ~700000000000001ZoUK@EZ=+Ze{cL_kwWV44oj5((59!HB1Y-xu0WaV@ z)XGX2E)Hr89v*r0sQ>#`U9b%pJI?M#N`k3dRp->LTUFO*9id@*4)d+R0V!Oq!T=^A zOua>9MeooDHC?gDvn{{yZW3AR=U5OLQn-GPyybHOEvXF`=fm?p{u#nJvVtFQn=;>L z5uAbMJ1khF(Gs60ELvH?J8J99XI9K$I5;1igXpiHEwVA}pAY*N7kq)^#YyBX(!@ht z1Tn?+UI1~JMmFPb7G6N8+%Q_jJ$Ut!X9y#qu?ii}Mcky>11n;%M#o-~FbCFA_=21r zNS>_(|1i|{{qWTbmSBg0!Hkxg@%u&$U@Oq;8cL1KijuFjQ*g;Kl&*U-}pyjPKub0KoA;)0X_)*)TxULAjkx6|{!tbx}1H+310y zO4IpBQ71h>3!rKyOqE;3#AT+|Bd8#*H|gR)}i%s;m?E63c6}G*!gw zshqh&o+Cw3M27WoFKc_ z2T{R&k>x+4u%i&ENr>8*&d_m?F6*8yGDV zN^Y-(zHuyNJ3Y9$`)8Y%xfh{zz6S415E6aDOA?d)#N0 z6Ek&@!eC(7B(t~im$yAxhsw9(CBQy7kA-8G66oXbMnd5sAz0Qd?-zdbD zJr**z$F~!dF^Ho(g@99xXf>vQq2%d;TE<+u$zwhcI%k5gw(K9)5^KuR57Lz&oSpS+ ze(*J=GBPj@tq{D`I*hPs2#uz@N}59Zm@!HM^Ps82dgHk&(MBCn#Z%y>fz7*%7hw5v zEt?I5o_{m@GO`FnfwkO^iXt}RMC{7pd^x2Oy~U?T`0Hp_Zg z+tMH*KO2o$_;rlgOq)Kc+AW=l(@3sE|2+s-Se&wQscAdo*$+3UWeR=s&1gFR4)#&f}EWvw>+0Yj2Cu=l1> z0DJk21O*cE#}jBkl&ys=*Qi9`gsnzjitIri%&6 zABv3YVqY5s+>L#X@CA=LUZH3K_tV9&tdfC&<7|+)t>$kpZ_QqfB1N6sBrn+p*Bkiv zZ!c)TYtw>X8>Kyav>}MLY^T|6W?KCBSC&y#)$+xZ<6|}tWFgp#zWtD#5w(+xWL6HbSd$A%|Zs*AY)Zsy>OGI}u zIPV-ph;wm*EE`oOocgYUY0XBVa9ecVspv&x=V zLiyBbWwyGMVK(0rOawY0d0J#*)Z;>oHzf-8;L09tH{m+Ckhc;2ghXcse{$<-Bn=2-B-qAa)|fn6i`$`2R`NK)pTh4SO;QMt{bk-7=D z+^LRSO{ikmRsExv6Kn@xGW6N0Rsx*{XqsktnYRMZZZ#huO!*g!e7gS9%z=B(8|^|t z-@pTBKdbC5Q38j(p_yzlpp}1S15qVbnIDoL5c6(O4pTYS&f8OdMWC!LaG{-cj@%pa zyUvl&e&)(^Jp7-#^bm^^Z#^aSpSk>;fcJm9{-A@y_n(7bg6PVfXzr%C!{0U)V`A;T z@cDEg3W#0U6{XXeZ>kR+g%+*vXUbGOH`kb)`erh`yxMMe+@d|-*l2Ic8$Vdw%r|`g wgK*G8ch^4nxq0WyHn}2f2eW~=UbDd2Ce(XnqTbD<*wbZgOy30l2f=AANkU?L*Z=?k literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumsta.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglnum/cglnumsta.go.i new file mode 100644 index 0000000000000000000000000000000000000000..ace3ab42bbe67b262b3389d9be4a85cc800ca46d GIT binary patch literal 1708 zcmV;d22=R}0RRC20000000wLT01zGk00000001HX|NsC0|NsBKP9zB?K&ZRNO2G5+ z%Wr+P0fEW@00000000000001ZoSj!occNGjUdykj$x4kek27Z$J(C3@8qOhL117pe zy&6s<*Wr=GnbZG$zPg~8#H5qyg-z;Kef8Dj7R7m6YXs3k#9^`^L$22{p`j!@nx$d7 zr89DhwMe6R7$3;|Jj|mkkLH=CH4M4grqSvlr>4=OtBcEvGyGiAAPtirbX$lx7Ac*R z8!tpME7BF7haz2v$rje0h((wQy6j$bFG!C!42v7k*V9})M0@`o_T zkAQU?%cm$=(Of2rh>bEf0*=VPy`hqkT<$o`&D{3EbM0Zt!K&>GBvzDR+pxE6Abo=9?) zR;>Y(bD5IFQA+DDN4JD=R_9k$L)jgW=WrYmDH}dZ!nI&3`&LY3eV{TO+!<&F^T)S_2KIu*$ zQYY}N-Z*d}IMIDro@fm|(VZ!olaXioKDi!Qw4(QhOj2rx^_bl5Ari#kI3LJJefH$2+x))f+*w#H7jlGfU z1B)Z;TfSlI)~(s^!asbHd1pES`8T?4zY5g7cTA7TzlgF2B-_$^wpqGDoPEnPjerBH zp9~}q1nmy_Bh#?>!JL?gM)#&2fMUM5j&FV+Lkp+W*KhS9qHF#lE2xVx_RL!*?GCht zKkoT~6^sLuhOXOJ$@Wd}&N58@PqJNKC2Z`Q9k>W|cFh>b7LM`U8~YaL4XJhl)APoo zz;c}ys(g>kAa)(LeU)L?QPCnvt~X^=PJ=2yhwg7o$WdoU1r~TZr@=?sjNniY9+Ac1 zAWU-1p=}LK$1wTSWte-*H(OjV%V!O%bbPPF>zKn0(co%Rtwa|4Fk|iMNO1DT{xSi1E&0 zyTvm**_&WZ+9C1bwmzKh4;fFZu*;S?y(Zwa%bzNW=AL8=tJ53dDORUe4T2V9kS&93 z|1Zd7S~K}7$YBagkYD)Q?liX_XmX?M$g%Q4X?B6vVlGW7FCk7}Hr9(v@yWi*-rSO1 zYh~TOY%)}-Q7Pb@UbTI5&$(0cY|+nF#m;;T*I}7K&1Rsj=wcUaYXpU=>bR zY7hHFAPn7nuCGP)paxbfG1btVDvkUH=M>gOobSZoDzN5m@}^Q~(J85i_H%uGON$Re z`9vhVezJK5$;K6tF#EzdVDHsUuR|`&!Vy>KhvR^QEOXTQs2WE@z-P{?{0a%#4sXR7 zmRfAAqD0`m`YWWfCU2>DiR5zs3h7Weq*P;79e5CmsBPh)Lp4BUxC?41%1@oL=-~Kn zaGzjYHOpZ$y_l$f(UlsE@axDN`?)MuyEhVr3w#^!M!k!HcYv-FI?d{`14@Yo;Y>wU z4#*ZzFE85a#9xQ_w9IlxCjW?34r&^&Tt0^QBvBQ^7tG`%r}e9-nu6#1=gF%S?(f8l zPF6YjMDAYQsG~QtBGcT@x3lWj?I;}`!d0o?+lO`=(EEFtcHY(+CiX$Bd;bBE>HjKK C(oL5D literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/_makefile.i new file mode 100644 index 0000000000000000000000000000000000000000..c8637496b6a2c387f883554c06b1327334affe2d GIT binary patch literal 593 zcmZQzWME_f14bVP2F5!OHiOlFD3Dp(p0qywqMhM7!Joc0Q*K^6+n)$k1EwnG)J`zW zKV%@#n*K-IuW6y|q$z%(OL;_`T3C8nUbcl;emlCcAm@q2f)$VUfA_F1dG+M^=Kba6 z`CLnM&K9GMMShZd_=UNztMz)Vcon#5 zPsICEAv<^R3dAZdnzCi-(!(0-quSJJ6Tj!r&Mouk&-uhW>G8+=j_1^mM!eP7{Na?^ z=Jgvd^12mn-}P7XUql_-8>XL|3?HnCxcrm%g2oI}P=JDB0SKgltk+-`1A{Gy21UoQ zZ_D2<{${%{ulQO!o9u%vPHH#aLe)Si#wwsbAZFm_Ois@!N=-@5P0>rwkKqEzGp2)8 zX#rWkz$^v^JCHEQ=m#uEFZ@Wk&+|xV+Rsi)Ms?PGybVw_Pzr2xCy*ltHM+E@0Bkgr KTa;Q1<^ljgi|NP! literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred.go.i new file mode 100644 index 0000000000000000000000000000000000000000..8087a5dea9c2116d455762fb1db7761821a9e364 GIT binary patch literal 9610 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 b5Vw;YV7?)ewR`5+!}wX|2S8{t`k?+Fm!<-- literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglred__test.go.i new file mode 100644 index 0000000000000000000000000000000000000000..2ae3a71ed193960980bed3e77dffae29f0c28d0a GIT binary patch literal 6348 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredcmd.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredcmd.go.i new file mode 100644 index 0000000000000000000000000000000000000000..d4235afaa10efc4b35633602c83d8f0b9fb8ab4a GIT binary patch literal 1281 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredurp.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglred/cglredurp.go.i new file mode 100644 index 0000000000000000000000000000000000000000..bdac1e208e07592f7eb3ae89ecc29e0bd0d19db9 GIT binary patch literal 4176 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 jwlhoO-7Auxxw+o|gHnN0 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsml/_makefile.i new file mode 100644 index 0000000000000000000000000000000000000000..7cf27e354bf5cb98dbf5ecf293764cc6f07bd752 GIT binary patch literal 486 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 Dv)kN* literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsmr.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsmr.go.i new file mode 100644 index 0000000000000000000000000000000000000000..0b5c0610f50468d7e11bbbac74a6cba224f2a99b GIT binary patch literal 3454 zcmXw+cRUo1|Hn_9Syr+yk?juYh_g4@d&?OiBPTPY6OoZU&&-N*WQQ|OR#uT6mz{lP zM#i`LeSWWhp0D@g@%rce{_Fh$5CMn)|3tM50C0W(KM&Bm`cD>NZ38Q?B-hQ*rcuXaBOg+` zrYVozADU-ZAr>uV;Fe3n@ir&(EMbb3{h#~ zxI9ayA;TfNWrLKLMZtzEV2Nn{z0Pp4)Q1z?`CPa}$nWMGCGSO&s~s*SfVccyr`p%@ z6kAq>Op%XBjlN^;z9t(LE@)@S~HZ~MzchtG?WkuEw?6znk@*Q{L3 zMQ}~ zR3B0JQcG@vs}VA*IU#TqnFk>qmau;k{?eh$3n$=@8;Mrs48UX1iJ-rD`p^KOcYV3F||qi)zZBG+m<2J%#BbPtS+9 z35FwP+MkN@^$r~frR{CP9%vFq5N}|@o7D!@5~JLil(R;TUzuyO>^9!o*}A>2S{c3P zqxq)*oO`{wE^}>W0sO52xiP#W;yb3Fu`rw{DokU(k-qMwbiA}pN`ot%7@qOM6`J9y z!666FpLTh?tZXE1?4R% zJ-i_SzK24#{|JBXjC9|*_q;Un#X6$#W!laLXTYVFE=33AV=HA2_xNW22eLb|kBf8) zhPd3}l~NL{ZRW&qGQNOq4i`3nH!jD#pkvSY9c2iK+yll#A-O*OEW}ueWKX-QYqMH_ zS#8)Y6gze3T3J?dg}3{Ebuj=Kk`ONDvdQw589@rPK*@7jigGB%is zV(cj6;LXI3EE)BB2^VRW@zUmxHOW@!b$@RGE+-R<#P<%MJ^Un-ru00aIMQLl;R8U@vyBA?IUwTA;ESy#z)iUg55b%fmE%FWWb`@ux#S0{#`!!@ZBxX zNZSltX7_q$QbeG_gI=IxoBL10d#(@&Q3qS9wlBCA{H- zFARbWd8dO~xzX<7LT6`tO$;@0%DN94kNk0qomNSWoNYRa?9qYAaKX3HoNId11p71o zk-ABeH^}T|GY;H4N0G{(i-klfVCbfAU|7ep^iQPqu5Iw~c!FR`Nui7_re9pnVM zXiJS01v={>DX)i;r`CvpRy0|nw_uehapI?Yqs_n|_T98(pPL@H4}q!2}EpWpPh;E9&sJbXs2 zfMSfy#NbD&JxzQC%fp2b1z*B_<~G7XW%Is2Sqz|XNYE2MJDf{J-75@rK@dz2swMY8 z7+NZM_6L(gA3g70Z9-m!27uxHvnKfRjrZZFdLE=88hXTBI@gFwmNEK>2$KfX_c`UF z5MJi``SNH~)F5Lm{8OCymP3xlq`iV)3Jg#=xBPng& zwic8vC=j$Wz-8@FL={;%x%XOABJAVV=qC7BdR!uBy^p7j){b`Or}<@%{+ZzmP)a+^ zEVE{&=O({}Ttk18w)K6iMb|fYb&&0ZaTbzz@ySD`rruCbPxQTJI#*`Y$HOt|b_zyU z6X*de>n+UEylae)aRQ{^_pam&Pn{~EQ2J$qv$L1;;qki3}8(e?s1qhtX;* zV>5;GPKqy0JequOBKW@MSjXp|X)%OS2#7dv=u>w| zw9pBz|BlMm2SZf>|Tk{lqrnc_qGIC}q&;rjl_1m0kgly9@e(G4iajvmM zNQ^oDwAt1LF7&jFPhd0WcCK}C?7t6qD4t46xP zwrG{q{U_TPs}K>2^Q+LOZr_GG8@{|obu@@4Z-dH?e+~dJ{L8pa+-<7ldjI-bwk{%X(#iozI>Ts@I5mQ-!{9jcvq?C@u9rJD72^^2 zfN40~WDe@oDvZ*B4{pYI7H&0^dmY|G9BVFg*m$xa9SBQ(*E%%{qC=l%!J^)U`8-xh z+e#Xr*njtX#B^dp`iGpkV|pnghJ#q(cp!97XFjM1ok!R}S+6R^DJV0c{k=eQ**JBF4}eoj Z2c>#!WqEs+X&Lrk=KtaU$7K8+{s%wqo=^Y) literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsrt.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsrt.go.i new file mode 100644 index 0000000000000000000000000000000000000000..11fc0607c2ae1d5667ecb0a179c8dcc9468ce38e GIT binary patch literal 1803 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/_makefile.i new file mode 100644 index 0000000000000000000000000000000000000000..3148a14245b8c3c01f2c8b29e0ffdc416acb0da6 GIT binary patch literal 828 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 Y5{8Yemm%-2sM7-(^b literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglsup/cglsup__test.go.i new file mode 100644 index 0000000000000000000000000000000000000000..aae4793b48326f87d9a481794f3520bbaa17578d GIT binary patch literal 3409 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/_makefile.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/_makefile.i new file mode 100644 index 0000000000000000000000000000000000000000..7d0581fd1ec11beab5df7478b2fb7afd559ed8a6 GIT binary patch literal 990 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl__test.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutl__test.go.i new file mode 100644 index 0000000000000000000000000000000000000000..71df63f9eb37c0ea51abb51b11ee4b2679759f88 GIT binary patch literal 5796 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 O%Ho>h9`cv$SpNqH6Xvi0 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlrre.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutlrre.go.i new file mode 100644 index 0000000000000000000000000000000000000000..1bbef82cdf3ce66d549877b62b294cbe5cd501ca GIT binary patch literal 1689 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 F`~#f8z&QW_ literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutltim.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutltim.go.i new file mode 100644 index 0000000000000000000000000000000000000000..fa83716be57d2d93b5ba7ed5219895656959fd16 GIT binary patch literal 2334 zcmV+(3E}nt0RRC20000000!0o02Mm`0000000030|NsC0|NsAju<#jKPKnN?_7hxL zuBq<}X1coo00000000000001ZoSj&0Z{j!*{!D(wTtA$kqAmNPJ>6dWAq_5A3JI5l zveoHyO2JTTLxPg9-DB8=bA+Y^xpGXd|eJJ%gBqvcBo2sQI8W8ybU(nZ#WSDC*+k{XRgGL_w6b&{Ck|6iIzUvl%WZ{c+=F`750WqL-|4 zqmeDegiZ^3NyK72y+#AI2)Ip}jAeD@(3n;ruk4?XvhcUc$ipCITnu-xI3$9w$% z`mWt&o)4ze#aSot`28qwapJ=C(euJ+(2D6i0sAuanD2w@0Ur!)j%Wz)nNGl&-v;hj z_NdF9UK7y4<&HlMh(;8slS3V2{iR!0(&3y_2Xrc9=)xx3auPB%7P}Hq)Un z&o1|v6;MK(k%i(RLAwq9kXf7t>pc3~B?~Fzz#)$9;BGVu5Fp3_i+c z1ywtYh$;q^G{Ip#oA;PwFs{=ncO-C6s@Q+y- zaiGY3HvT4E3EnuW~+FjUJG^igh2RM<50r0L7uMgru(Vk0-enkT#?}pCe2>^kr2yfoE?Cj z;YGc{_45$-Lnsvs*m(l4vt~;TiV#i0(J&P4_G$x33p4noSR?{#<+gIbH*%H6pzVyG zr?wqyk*T7h{Xez&Rv1n2v51pQ&~uiRd+lTcIZ4ae<|J9gdAYyp1AaikN3UJNJMjU2 zR@@_eCu_JLjHJ+76*#{p(q7O#q=Ag_w4X!rcR)UMsu+E2U(R!>#@R*ahHvKpszEN{ z{l}{NSctFZ{3{_Y;WyJfCMgH)|i2y=Y%W7Xx9r{M_=d2HiM zQ(0cB3ZY}zRv;Pt_4iKkV`~Nf=v6xJ*woHNVM`~R7!U>_!`+>>qlNO6>tm1SzIya^ z;cX`po=!sr-p<3Lsr^J2GNyGLgx?jdos0?&&B6|D?=~s4;MZTFxyk7Eu0&}W`?}-T z1M0ME2tOdpW6CR-Li#0r7fpr0l<~8sVA^BL^N>{7rq`=-x^Rw( zMIg1+BA~)$U$2vNwgl6Bjw`0aVB$2WsafH(<9x74)%{(sN|ou+GSv@3?K)NFYqtZH zdYagFsTRym)M^Q}jzocirOCTH=y*OgO)t=;zJJVR_t&XU=2 zIm>XUg&x+FbM1Ek;*gxL*Z|bM1IOC-n4kqzZAA;XjpM$i=h$tDx~6wr)pbbJq!`!K zb>n#urFFWE?lXJHyyM@+s!3C0p0D#P|3`##>z=x*q#Dy|Tbu4^Uvy707mH2zqzsGZ zN&92tq)h%_|HrUxSDwWr1$%Jv0b z47cQkID!{HE;8A*V6SiD`!;kdT1$3pS*I~o;2YgD;T*0;U z>=GDoPvx*1&~R)21dFDmO!;^(-{~zdVy*g0ORQ$ E+yFyl$N&HU literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutluid.go.i b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/store/data/cglutl/cglutluid.go.i new file mode 100644 index 0000000000000000000000000000000000000000..363e7dbfa9b7243b79b3e21226ff47b7d7adb68e GIT binary patch literal 2883 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 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/tags.cache b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/tags.cache new file mode 100644 index 0000000..7f2cacb --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/tags.cache @@ -0,0 +1,6 @@ +95 0e0559350cc3c90b3a51dd98ac3ba577db027317 d11eb24f9c4089a5d83f315625407b7bf1811bb4 + +23ee9664f914f12079d78fdb6e8d5745387b0394 release +440721520a9cc613e0999c70c40e8e2bb7c70cfb release.2011-06-23 +5353419f1ba694ba7a425e6a6fcd45ea97884560 release.2011-07-28 +23ee9664f914f12079d78fdb6e8d5745387b0394 release.2011-08-02 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.branch b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.branch new file mode 100644 index 0000000..331d858 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.branch @@ -0,0 +1 @@ +default \ No newline at end of file diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.desc b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.desc new file mode 100644 index 0000000..e96d029 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.desc @@ -0,0 +1,3 @@ +0 +pull +https://tideland-cgl.googlecode.com/hg diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.dirstate b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hg/undo.dirstate new file mode 100644 index 0000000..e69de29 diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hgtags b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hgtags new file mode 100644 index 0000000..e7727eb --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/.hgtags @@ -0,0 +1,5 @@ +440721520a9cc613e0999c70c40e8e2bb7c70cfb release.2011-06-23 +440721520a9cc613e0999c70c40e8e2bb7c70cfb release +5353419f1ba694ba7a425e6a6fcd45ea97884560 release.2011-07-28 +440721520a9cc613e0999c70c40e8e2bb7c70cfb release +5353419f1ba694ba7a425e6a6fcd45ea97884560 release diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/LICENSE.txt b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/LICENSE.txt new file mode 100644 index 0000000..360008e --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/LICENSE.txt @@ -0,0 +1,28 @@ +Tideland Common Go Library + +Redistribution and use in source and binary forms, with or +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 Tideland 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 OWNER 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. diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/Makefile b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/Makefile new file mode 100644 index 0000000..fe8deda --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/Makefile @@ -0,0 +1,31 @@ +# Tideland Common Go Library +# +# Copyright 2009-2011 Frank Mueller / Oldenburg / Germany. +# +# All rights reserved. Use of this source code is +# governed by a BSD-style license that can be found +# in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=tideland-cgl.googlecode.com/hg +GOFMT=gofmt -w -tabindent -tabwidth=8 + +GOFILES=\ + cgl.go\ + cglsup.go\ + cglfsm.go\ + cglmon.go\ + cglsmr.go\ + cgltim.go\ + cglsml.go\ + +include $(GOROOT)/src/Make.pkg + +format: + ${GOFMT} ${GOFILES} + ${GOFMT} cgl_test.go + +# +# EOF +# diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl.go new file mode 100644 index 0000000..295e4c7 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl.go @@ -0,0 +1,288 @@ +/* + Tideland Common Go Library + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + 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 Tideland 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 OWNER 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. +*/ + +// The package 'cgl' contains a lot of helpful stuff for many kinds of software. Those +// are a map/reduce, sorting, time handling, UUIDs, lazy evaluation, chronological jobs, +// state machines, monitoring, suervision, a simple markup language and much more. +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "bytes" + "crypto/rand" + "fmt" + "encoding/hex" + "io" + "log" + "reflect" + "runtime" + "strings" + "unicode" +) + +//-------------------- +// CONST +//-------------------- + +const RELEASE = "Tideland Common Go Library Release 2011-08-02" + +//-------------------- +// DEBUGGING +//-------------------- + +// Debug prints a debug information to the log with file and line. +func Debug(format string, a ...interface{}) { + _, file, line, _ := runtime.Caller(1) + info := fmt.Sprintf(format, a...) + + log.Printf("[cgl] debug %s:%d %v", file, line, info) +} + +//-------------------- +// UUID +//-------------------- + +// UUID represent a universal identifier with 16 bytes. +type UUID []byte + +// NewUUID generates a new UUID based on version 4. +func NewUUID() UUID { + uuid := make([]byte, 16) + + _, err := io.ReadFull(rand.Reader, uuid) + + if err != nil { + log.Fatal(err) + } + + // Set version (4) and variant (2). + + var version byte = 4 << 4 + var variant byte = 2 << 4 + + uuid[6] = version | (uuid[6] & 15) + uuid[8] = variant | (uuid[8] & 15) + + return uuid +} + +// Raw returns a copy of the UUID bytes. +func (uuid UUID) Raw() []byte { + raw := make([]byte, 16) + + copy(raw, uuid[0:16]) + + return raw +} + +// String returns a hexadecimal string representation with +// standardized separators. +func (uuid UUID) String() string { + base := hex.EncodeToString(uuid.Raw()) + + return base[0:8] + "-" + base[8:12] + "-" + base[12:16] + "-" + base[16:20] + "-" + base[20:32] +} + +//-------------------- +// MORE ID FUNCTIONS +//-------------------- + +// LimitedSepIdentifier builds an identifier out of multiple parts, +// all as lowercase strings and concatenated with the separator +// Non letters and digits are exchanged with dashes and +// reduced to a maximum of one each. If limit is true only +// 'a' to 'z' and '0' to '9' are allowed. +func LimitedSepIdentifier(sep string, limit bool, parts ...interface{}) string { + iparts := make([]string, 0) + + for _, p := range parts { + tmp := strings.Map(func(r int) int { + // Check letter and digit. + if unicode.IsLetter(r) || unicode.IsDigit(r) { + lcr := unicode.ToLower(r) + + if limit { + // Only 'a' to 'z' and '0' to '9'. + if lcr <= unicode.MaxASCII { + return lcr + } else { + return ' ' + } + } else { + // Every char is allowed. + return lcr + } + } + + return ' ' + }, fmt.Sprintf("%v", p)) + + // Only use non-empty identifier parts. + if ipart := strings.Join(strings.Fields(tmp), "-"); len(ipart) > 0 { + iparts = append(iparts, ipart) + } + } + + return strings.Join(iparts, sep) +} + +// SepIdentifier builds an identifier out of multiple parts, all +// as lowercase strings and concatenated with the separator +// Non letters and digits are exchanged with dashes and +// reduced to a maximum of one each. +func SepIdentifier(sep string, parts ...interface{}) string { + return LimitedSepIdentifier(sep, false, parts...) +} + +// Identifier works like SepIdentifier but the seperator +// is set to be a colon. +func Identifier(parts ...interface{}) string { + return SepIdentifier(":", parts...) +} + +// TypeAsIdentifierPart transforms the name of the arguments type into +// a part for identifiers. It's splitted at each uppercase char, +// concatenated with dashes and transferred to lowercase. +func TypeAsIdentifierPart(i interface{}) string { + var buf bytes.Buffer + + fullTypeName := reflect.TypeOf(i).String() + lastDot := strings.LastIndex(fullTypeName, ".") + typeName := fullTypeName[lastDot+1:] + + for i, r := range typeName { + if unicode.IsUpper(r) { + if i > 0 { + buf.WriteRune('-') + } + } + + buf.WriteRune(r) + } + + return strings.ToLower(buf.String()) +} + +//-------------------- +// METHOD DISPATCHING +//-------------------- + +// Dispatch a string to a method of a type. +func Dispatch(variable interface{}, name string, args ...interface{}) ([]interface{}, bool) { + numArgs := len(args) + value := reflect.ValueOf(variable) + valueType := value.Type() + numMethods := valueType.NumMethod() + + for i := 0; i < numMethods; i++ { + method := valueType.Method(i) + + if (method.PkgPath == "") && (method.Type.NumIn() == numArgs+1) { + + if method.Name == name { + // Prepare all args with variable and args. + + callArgs := make([]reflect.Value, numArgs+1) + + callArgs[0] = value + + for i, a := range args { + callArgs[i+1] = reflect.ValueOf(a) + } + + // Make the function call. + + results := method.Func.Call(callArgs) + + // Transfer results into slice of interfaces. + + allResults := make([]interface{}, len(results)) + + for i, v := range results { + allResults[i] = v.Interface() + } + + return allResults, true + } + } + } + + return nil, false +} + +//-------------------- +// LAZY EVALUATOR BUILDERS +//-------------------- + +// Function to evaluate. +type EvalFunc func(interface{}) (interface{}, interface{}) + +// Generic builder for lazy evaluators. +func BuildLazyEvaluator(evalFunc EvalFunc, initState interface{}) func() interface{} { + retValChan := make(chan interface{}) + + loopFunc := func() { + var actState interface{} = initState + var retVal interface{} + + for { + retVal, actState = evalFunc(actState) + + retValChan <- retVal + } + } + + retFunc := func() interface{} { + return <-retValChan + } + + go loopFunc() + + return retFunc +} + +// Builder for lazy evaluators with ints as result. +func BuildLazyIntEvaluator(evalFunc EvalFunc, initState interface{}) func() int { + ef := BuildLazyEvaluator(evalFunc, initState) + + return func() int { + return ef().(int) + } +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl_test.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl_test.go new file mode 100644 index 0000000..1d713f8 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgl_test.go @@ -0,0 +1,972 @@ +/* + Tideland Common Go Library - Unit Tests + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + 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 Tideland 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 OWNER 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. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "bytes" + "fmt" + "log" + "rand" + "sort" + "strconv" + "strings" + "testing" + "time" +) + +//-------------------- +// TESTS +//-------------------- + +// Test single recovering. +func TestSingleRecovering(t *testing.T) { + s := NewSupervisor(nil) + ra := NewRecoverableAction(s) + + pos := ra.Action(PositiveAction) + + if pos == "OK" { + t.Logf("Single recovering (a) OK.") + } else { + t.Errorf("Single recovering (a) failed! Reply is '%v'.", pos) + } + + neg := ra.Action(FailAction) + + if neg == "Recovered" { + t.Logf("Single recovering (b) OK.") + } else { + t.Errorf("Single recovering (b) failed! Reply is '%v.", neg) + } +} + +// Test multiple recovering. +func TestMultipleRecovering(t *testing.T) { + s := NewSupervisor(nil) + raa := NewRecoverableAction(s) + rab := NewRecoverableAction(s) + rac := NewRecoverableAction(s) + + s.AddRecoverable("A", raa) + s.AddRecoverable("B", rab) + s.AddRecoverable("C", rac) + + t.Logf("(A) is '%v'.", raa.Action(FailAction)) + t.Logf("(B) is '%v'.", rab.Action(PositiveAction)) + t.Logf("(C) is '%v'.", rac.Action(PositiveAction)) +} + +// Test single heartbeat timeout. +func TestSingleHeartbeatTimeout(t *testing.T) { + ra := NewRecoverableAction(nil) + reply := ra.Action(TimeConsumingAction) + + if reply == "Recovered" { + t.Logf("Heartbeat timeout recovering OK.") + } else { + t.Errorf("Heartbeat timeout recovering failed! Reply is '%v.", reply) + } +} + +// Test multiple heartbeat timeout. +func TestMultipleHeartbeatTimeout(t *testing.T) { + s := NewSupervisor(nil) + raa := NewRecoverableAction(s) + rab := NewRecoverableAction(s) + rac := NewRecoverableAction(s) + + s.AddRecoverable("A", raa) + s.AddRecoverable("B", rab) + s.AddRecoverable("C", rac) + + t.Logf("(A) is '%v'.", raa.Action(TimeConsumingAction)) + t.Logf("(B) is '%v'.", rab.Action(PositiveAction)) + t.Logf("(C) is '%v'.", rac.Action(PositiveAction)) +} + +// Test the finite state machine successfully. +func TestFsmSuccess(t *testing.T) { + fsm := NewFSM(NewLoginHandler(), -1) + + fsm.Send(&LoginPayload{"yadda"}) + fsm.Send(&PreparePayload{"foo", "bar"}) + fsm.Send(&LoginPayload{"yaddaA"}) + fsm.Send(&LoginPayload{"yaddaB"}) + fsm.Send(&LoginPayload{"yaddaC"}) + fsm.Send(&LoginPayload{"yaddaD"}) + fsm.Send(&UnlockPayload{}) + fsm.Send(&LoginPayload{"bar"}) + + time.Sleep(1e7) + + t.Logf("Status: '%v'.", fsm.State()) +} + +// Test the finite state machine with timeout. +func TestFsmTimeout(t *testing.T) { + fsm := NewFSM(NewLoginHandler(), 1e5) + + fsm.Send(&LoginPayload{"yadda"}) + fsm.Send(&PreparePayload{"foo", "bar"}) + fsm.Send(&LoginPayload{"yaddaA"}) + fsm.Send(&LoginPayload{"yaddaB"}) + + time.Sleep(1e8) + + fsm.Send(&LoginPayload{"yaddaC"}) + fsm.Send(&LoginPayload{"yaddaD"}) + fsm.Send(&UnlockPayload{}) + fsm.Send(&LoginPayload{"bar"}) + + time.Sleep(1e7) + + t.Logf("Status: '%v'.", fsm.State()) +} + +// Test dispatching. +func TestDispatching(t *testing.T) { + tt := new(TT) + + v1, ok1 := Dispatch(tt, "Add", 4, 5) + v2, ok2 := Dispatch(tt, "Add", 4, 5, 6) + v3, ok3 := Dispatch(tt, "Mul", 4, 5, 6) + v4, ok4 := Dispatch(tt, "Mul", 4, 5, 6, 7, 8) + + t.Logf("Add 1: %v / %v\n", v1, ok1) + t.Logf("Add 2: %v / %v\n", v2, ok2) + t.Logf("Mul 1: %v / %v\n", v3, ok3) + t.Logf("Mul 2: %v / %v\n", v4, ok4) +} + +// Test debug statement. +func TestDebug(t *testing.T) { + Debug("Hello, I'm debugging %v!", "here") +} + +// Test nanoseconds calculation. +func TestNanoseconds(t *testing.T) { + t.Logf("Microseconds: %v\n", NsMicroseconds(4711)) + t.Logf("Milliseconds: %v\n", NsMilliseconds(4711)) + t.Logf("Seconds : %v\n", NsSeconds(4711)) + t.Logf("Minutes : %v\n", NsMinutes(4711)) + t.Logf("Hours : %v\n", NsHours(4711)) + t.Logf("Days : %v\n", NsDays(4711)) + t.Logf("Weeks : %v\n", NsWeeks(4711)) +} + +// Test time containments. +func TestTimeContainments(t *testing.T) { + now := time.UTC() + years := []int64{2008, 2009, 2010} + months := []int{3, 6, 9, 12} + days := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + hours := []int{20, 21, 22, 23} + minutes := []int{5, 10, 15, 20, 25, 30} + seconds := []int{0, 15, 30, 45} + weekdays := []int{time.Saturday, time.Sunday} + + t.Logf("Time is %s\n", now.Format(time.RFC822)) + t.Logf("Year in list : %t\n", YearInList(now, years)) + t.Logf("Year in range : %t\n", YearInRange(now, 2000, 2005)) + t.Logf("Month in list : %t\n", MonthInList(now, months)) + t.Logf("Month in range : %t\n", MonthInRange(now, 1, 6)) + t.Logf("Day in list : %t\n", DayInList(now, days)) + t.Logf("Day in range : %t\n", DayInRange(now, 15, 25)) + t.Logf("Hour in list : %t\n", HourInList(now, hours)) + t.Logf("Hour in range : %t\n", HourInRange(now, 9, 17)) + t.Logf("Minute in list : %t\n", MinuteInList(now, minutes)) + t.Logf("Minute in range : %t\n", MinuteInRange(now, 0, 29)) + t.Logf("Second in list : %t\n", SecondInList(now, seconds)) + t.Logf("Second in range : %t\n", SecondInRange(now, 30, 59)) + t.Logf("Weekday in list : %t\n", WeekdayInList(now, weekdays)) + t.Logf("Weekday in range: %t\n", WeekdayInRange(now, time.Monday, time.Friday)) +} + +// Test the UUID. +func TestUuid(t *testing.T) { + uuids := make(map[string]bool) + + t.Logf("Start generating UUIDs ...") + + for i := 0; i < 1000000; i++ { + uuid := NewUUID().String() + + if uuids[uuid] { + t.Fatalf("UUID collision") + } + + uuids[uuid] = true + } + + t.Logf("Done generating UUIDs!") +} + +// Test the creation of an identifier. +func TestIdentifier(t *testing.T) { + // Type as identifier. + var kvlf KeyValueLessFunc + + idp := TypeAsIdentifierPart(kvlf) + + if idp != "key-value-less-func" { + t.Errorf("Identifier part for KeyValueLessFunc is wrong, returned '%v'!", idp) + } + + idp = TypeAsIdentifierPart(NewUUID()) + + if idp != "u-u-i-d" { + t.Errorf("Identifier part for UUID is wrong, returned '%v'!", idp) + } + + // Identifier. + id := Identifier("One", 2, "three four") + + if id != "one:2:three-four" { + t.Errorf("First identifier is wrong! Id: %v", id) + } + + id = Identifier(2011, 6, 22, "One, two, or three things.") + + if id != "2011:6:22:one-two-or-three-things" { + t.Errorf("Second identifier is wrong! Id: %v", id) + } + + id = SepIdentifier("+", 1, "oNe", 2, "TWO", "3", "ÄÖÜ") + + if id != "1+one+2+two+3+äöü" { + t.Errorf("Third identifier is wrong! Id: %v", id) + } + + id = LimitedSepIdentifier("+", true, " ", 1, "oNe", 2, "TWO", "3", "ÄÖÜ", "Four", "+#-:,") + + if id != "1+one+2+two+3+four" { + t.Errorf("Fourth identifier is wrong! Id: %v", id) + } +} + +// Test the integer generator. +func TestLazyIntEvaluator(t *testing.T) { + fibFunc := func(s interface{}) (interface{}, interface{}) { + os := s.([]int) + v1 := os[0] + v2 := os[1] + ns := []int{v2, v1 + v2} + + return v1, ns + } + + fib := BuildLazyIntEvaluator(fibFunc, []int{0, 1}) + + var fibs [25]int + + for i := 0; i < 25; i++ { + fibs[i] = fib() + } + + t.Logf("FIBS: %v", fibs) +} + +// Test pivot. +func TestPivot(t *testing.T) { + a := make(sort.IntSlice, 15) + + for i := 0; i < len(a); i++ { + a[i] = rand.Intn(99) + } + + plo, phi := partition(a, 0, len(a)-1) + + t.Logf("PLO : %v", plo) + t.Logf("PHI : %v", phi) + t.Logf("PDATA: %v", a[phi-1]) + t.Logf("PIVOT: %v", a) +} + +// Test sort shootout. +func TestSort(t *testing.T) { + ola := generateTestOrdersList(25000) + olb := generateTestOrdersList(25000) + olc := generateTestOrdersList(25000) + old := generateTestOrdersList(25000) + + ta := time.Nanoseconds() + Sort(ola) + tb := time.Nanoseconds() + sort.Sort(olb) + tc := time.Nanoseconds() + insertionSort(olc, 0, len(olc)-1) + td := time.Nanoseconds() + sequentialQuickSort(old, 0, len(olc)-1) + te := time.Nanoseconds() + + t.Logf("PQS: %v", tb-ta) + t.Logf(" QS: %v", tc-tb) + t.Logf(" IS: %v", td-tc) + t.Logf("SQS: %v", te-td) +} + +// Test the parallel quicksort function. +func TestParallelQuickSort(t *testing.T) { + ol := generateTestOrdersList(10000) + + Sort(ol) + + cn := 0 + + for _, o := range ol { + if cn > o.CustomerNo { + t.Errorf("Customer No %v in wrong order!", o.CustomerNo) + + cn = o.CustomerNo + } else { + cn = o.CustomerNo + } + } +} + +// Test the MapReduce function. +func TestMapReduce(t *testing.T) { + // Start data producer. + + orderChan := generateTestOrders(2000) + + // Define map and reduce functions. + + mapFunc := func(in *KeyValue, mapEmitChan KeyValueChan) { + o := in.Value.(*Order) + + // Emit analysis data for each item. + + for _, i := range o.Items { + unitDiscount := (i.UnitPrice / 100.0) * i.DiscountPerc + totalDiscount := unitDiscount * float64(i.Count) + totalAmount := (i.UnitPrice - unitDiscount) * float64(i.Count) + analysis := &OrderItemAnalysis{i.ArticleNo, i.Count, totalAmount, totalDiscount} + articleNo := strconv.Itoa(i.ArticleNo) + + mapEmitChan <- &KeyValue{articleNo, analysis} + } + } + + reduceFunc := func(inChan KeyValueChan, reduceEmitChan KeyValueChan) { + memory := make(map[string]*OrderItemAnalysis) + + // Collect emitted analysis data. + + for kv := range inChan { + analysis := kv.Value.(*OrderItemAnalysis) + + if existing, ok := memory[kv.Key]; ok { + existing.Quantity += analysis.Quantity + existing.Amount += analysis.Amount + existing.Discount += analysis.Discount + } else { + memory[kv.Key] = analysis + } + } + + // Emit it to map/reduce caller. + + for articleNo, analysis := range memory { + reduceEmitChan <- &KeyValue{articleNo, analysis} + } + } + + // Now call MapReduce. + + for result := range SortedMapReduce(orderChan, mapFunc, 100, reduceFunc, 20, KeyLessFunc) { + t.Logf("%v\n", result.Value) + } +} + +// Test job. +func TestJob(t *testing.T) { + // Check function. + + cf := func(now *time.Time) (perform, delete bool) { + perform = now.Day == 1 && + now.Hour == 22 && + now.Minute == 0 && + SecondInList(now, []int{0, 10, 20, 30, 40, 50}) + delete = false + + return perform, delete + } + + // Task function. + + tf := func(id string) { t.Logf("Performed job %s\n", id) } + + // Job and time. + + job := NewJob("test-job-a", cf, tf) + time := time.LocalTime() + + // Test with non-matching time. + + time.Second = 1 + + job.checkAndPerform(time) + + // Test with matching time + + time.Day = 1 + time.Hour = 22 + time.Minute = 0 + time.Second = 0 + + job.checkAndPerform(time) +} + +// Test crontab keeping the job. +func TestCrontabKeep(t *testing.T) { + ctb := NewCrontab() + job := createJob(t, "keep", false) + + ctb.AddJob(job) + time.Sleep(10 * 1e9) + ctb.Stop() +} + +// Test crontab deleting the job. +func TestCrontabDelete(t *testing.T) { + ctb := NewCrontab() + job := createJob(t, "delete", true) + + ctb.AddJob(job) + time.Sleep(10 * 1e9) + ctb.Stop() +} + +// Test creating. +func TestSmlCreating(t *testing.T) { + root := createSmlStructure() + + t.Logf("Root: %v", root) +} + +// Test SML writer processing. +func TestSmlWriterProcessing(t *testing.T) { + root := createSmlStructure() + bufA := bytes.NewBufferString("") + bufB := bytes.NewBufferString("") + sppA := NewSmlWriterProcessor(bufA, true) + sppB := NewSmlWriterProcessor(bufB, false) + + root.ProcessWith(sppA) + root.ProcessWith(sppB) + + t.Logf("Print A: %v", bufA) + t.Logf("Print B: %v", bufB) +} + +// Test positive reading. +func TestSmlPositiveReading(t *testing.T) { + sml := "Before! {foo {bar:1:first Yadda ^{Test^} 1} {inbetween} {bar:2:last Yadda {Test ^^} 2}} After!" + reader := NewSmlReader(strings.NewReader(sml)) + + root, err := reader.RootTagNode() + + if err == nil { + t.Logf("Root:%v", root) + } else { + t.Errorf("Error: %v", err) + } +} + +// Test negative reading. +func TestSmlNegativeReading(t *testing.T) { + sml := "{Foo {bar:1 Yadda {test} {} 1} {bar:2 Yadda 2}}" + reader := NewSmlReader(strings.NewReader(sml)) + + root, err := reader.RootTagNode() + + if err == nil { + t.Errorf("Root: %v", root) + } else { + t.Logf("Error: %v", err) + } +} + +// Test of the ETM monitor. +func TestEtmMonitor(t *testing.T) { + mon := Monitor() + + // Generate measurings. + for i := 0; i < 500; i++ { + n := rand.Intn(10) + id := fmt.Sprintf("Work %d", n) + m := mon.BeginMeasuring(id) + + work(n * 5000) + + m.EndMeasuring() + } + + // Print, process with error, and print again. + mon.MeasuringPointsPrintAll() + + mon.MeasuringPointsDo(func(mp *MeasuringPoint) { + if mp.Count >= 25 { + // Divide by zero. + mp.Count = mp.Count / (mp.Count - mp.Count) + } + }) + + mon.MeasuringPointsPrintAll() +} + +// Test of the SSI monitor. +func TestSsiMonitor(t *testing.T) { + mon := Monitor() + + // Generate values. + for i := 0; i < 500; i++ { + n := rand.Intn(10) + id := fmt.Sprintf("Work %d", n) + + mon.SetValue(id, rand.Int63n(2001)-1000) + } + + // Print, process with error, and print again. + mon.StaySetVariablesPrintAll() + + mon.StaySetVariablesDo(func(ssv *StaySetVariable) { + if ssv.Count >= 25 { + // Divide by zero. + ssv.Count = ssv.Count / (ssv.Count - ssv.Count) + } + }) + + mon.StaySetVariablesPrintAll() +} + +// Test of the DSR monitor. +func TestDsrMonitor(t *testing.T) { + mon := Monitor() + + mon.Register("monitor:dsr:a", func() string { return "A" }) + mon.Register("monitor:dsr:b", func() string { return "4711" }) + mon.Register("monitor:dsr:c", func() string { return "2011-05-07" }) + + mon.DynamicStatusValuesPrintAll() +} + +//-------------------- +// HELPERS +//-------------------- + +// Test type. +type TT struct{} + +func (tt *TT) Add(a, b int) int { return a + b } + +func (tt *TT) Mul(a, b, c, d, e int) int { return a * b * c * d * e } + +// Order item type. +type OrderItem struct { + ArticleNo int + Count int + UnitPrice float64 + DiscountPerc float64 +} + +// Order type. +type Order struct { + OrderNo UUID + CustomerNo int + Items []*OrderItem +} + +func (o *Order) String() string { + msg := "ON: %v / CN: %4v / I: %v" + + return fmt.Sprintf(msg, o.OrderNo, o.CustomerNo, len(o.Items)) +} + +// Order item analysis type. +type OrderItemAnalysis struct { + ArticleNo int + Quantity int + Amount float64 + Discount float64 +} + +func (oia *OrderItemAnalysis) String() string { + msg := "AN: %5v / Q: %4v / A: %10.2f € / D: %10.2f €" + + return fmt.Sprintf(msg, oia.ArticleNo, oia.Quantity, oia.Amount, oia.Discount) +} + +// Order list. +type OrderList []*Order + +func (l OrderList) Len() int { + return len(l) +} + +func (l OrderList) Less(i, j int) bool { + return l[i].CustomerNo < l[j].CustomerNo +} + +func (l OrderList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + +// Action function. +type Action func() string + +// A positive action. +func PositiveAction() string { + log.Printf("Perform positive action.") + + return "OK" +} + +// A failing action. +func FailAction() string { + log.Printf("Perform failing action!") + + panic("Fail!") + + return "Fail!" +} + +// A time consuming action. +func TimeConsumingAction() string { + log.Printf("Perform time consuming action!") + + time.Sleep(3e8) + + return "Time consumed" +} + +// Recoverable action type. +type RecoverableAction struct { + actionChan chan Action + replyChan chan string + supervisor *Supervisor + heartbeat *Heartbeat +} + +// Create a new recoverable action. +func NewRecoverableAction(supervisor *Supervisor) *RecoverableAction { + ra := &RecoverableAction{ + actionChan: make(chan Action), + replyChan: make(chan string, 5), + supervisor: supervisor, + } + + ra.heartbeat = NewHeartbeat(ra, 1e8) + + go ra.backend() + + return ra +} + +// Send an action to perform. +func (ra *RecoverableAction) Action(action Action) string { + ra.actionChan <- action + + return <-ra.replyChan +} + +// Implement Supervisor() of the recoverable interface. +func (ra *RecoverableAction) Supervisor() *Supervisor { + return ra.supervisor +} + +// Implement Recover() of the recoverable interface. +func (ra *RecoverableAction) Recover(r Recoverable, err interface{}) { + if ra == r { + log.Printf("Recovering error '%v'!", err) + + ra.replyChan <- "Recovered" + + go ra.backend() + } +} + +// Backend of the recoverable action. +func (ra *RecoverableAction) backend() { + defer func() { + HelpIfNeeded(ra, recover()) + }() + + for { + select { + case action := <-ra.actionChan: + ra.replyChan <- action() + case h := <-ra.heartbeat.HeartbeatChan: + ImAlive(h) + } + } +} + +// Generate a test order. +func generateTestOrders(count int) KeyValueChan { + articleMaxNo := 9999 + unitPrices := make([]float64, articleMaxNo+1) + + for i := 0; i < articleMaxNo+1; i++ { + unitPrices[i] = rand.Float64() * 100.0 + } + + kvc := make(KeyValueChan) + + go func() { + for i := 0; i < count; i++ { + order := new(Order) + + order.OrderNo = NewUUID() + order.CustomerNo = rand.Intn(999) + 1 + order.Items = make([]*OrderItem, rand.Intn(9)+1) + + for j := 0; j < len(order.Items); j++ { + articleNo := rand.Intn(articleMaxNo) + + order.Items[j] = &OrderItem{ + ArticleNo: articleNo, + Count: rand.Intn(9) + 1, + UnitPrice: unitPrices[articleNo], + DiscountPerc: rand.Float64() * 4.0, + } + } + + kvc <- &KeyValue{order.OrderNo.String(), order} + } + + close(kvc) + }() + + return kvc +} + +// Generate a list with test orders. +func generateTestOrdersList(count int) OrderList { + l := make(OrderList, count) + idx := 0 + + for kv := range generateTestOrders(count) { + l[idx] = kv.Value.(*Order) + + idx++ + } + + return l +} + +// Create a job that leads to a an event every 2 seconds. +func createJob(t *testing.T, descr string, delete bool) *Job { + cf := func(now *time.Time) (bool, bool) { return now.Seconds()%2 == 0, delete } + tf := func(id string) { t.Logf("Performed job %s\n", id) } + + return NewJob("test-server-"+descr, cf, tf) +} + +// Create a SML structure. +func createSmlStructure() *TagNode { + root := NewTagNode("root") + + root.AppendText("Text A") + root.AppendText("Text B") + + root.AppendTaggedText("comment", "A first comment.") + + subA := root.AppendTag("sub-a:1st:important") + + subA.AppendText("Text A.A") + + root.AppendTaggedText("comment", "A second comment.") + + subB := root.AppendTag("sub-b:2nd") + + subB.AppendText("Text B.A") + subB.AppendTaggedText("raw", "Any raw text with {, }, and ^.") + + return root +} + +// Do some work. +func work(n int) int { + if n < 0 { + return 0 + } + + return n * work(n-1) +} + +//-------------------- +// TEST LOGIN EVENT HANDLER +//-------------------- + +// Prepare payload. +type PreparePayload struct { + userId string + password string +} + +// Login payload. +type LoginPayload struct { + password string +} + +// Reset payload. +type ResetPayload struct{} + +// Unlock payload. +type UnlockPayload struct{} + +// Login handler tyoe. +type LoginHandler struct { + userId string + password string + illegalLoginCounter int + locked bool +} + +// Create a new login handler. +func NewLoginHandler() *LoginHandler { + return new(LoginHandler) +} + +// Return the initial state. +func (lh *LoginHandler) Init() string { + return "New" +} + +// Terminate the handler. +func (lh *LoginHandler) Terminate(string, interface{}) string { + return "LoggedIn" +} + +// Handler for state: "New". +func (lh *LoginHandler) HandleStateNew(c *Condition) (string, interface{}) { + switch pld := c.Payload.(type) { + case *PreparePayload: + lh.userId = pld.userId + lh.password = pld.password + lh.illegalLoginCounter = 0 + lh.locked = false + + log.Printf("User '%v' prepared.", lh.userId) + + return "Authenticating", nil + case *LoginPayload: + log.Printf("Illegal login, handler not initialized!") + + return "New", false + case Timeout: + log.Printf("Timeout, terminate handler!") + + return "Terminate", nil + } + + log.Printf("Illegal payload '%v' during state 'new'!", c.Payload) + + return "New", nil +} + +// Handler for state: "Authenticating". +func (lh *LoginHandler) HandleStateAuthenticating(c *Condition) (string, interface{}) { + switch pld := c.Payload.(type) { + case *LoginPayload: + if pld.password == lh.password { + lh.illegalLoginCounter = 0 + lh.locked = false + + log.Printf("User '%v' logged in.", lh.userId) + + return "Terminate", true + } + + log.Printf("User '%v' used illegal password.", lh.userId) + + lh.illegalLoginCounter++ + + if lh.illegalLoginCounter == 3 { + lh.locked = true + + log.Printf("User '%v' locked!", lh.userId) + + return "Locked", false + } + + return "Authenticating", false + case *UnlockPayload: + log.Printf("No need to unlock user '%v'!", lh.userId) + + return "Authenticating", nil + case *ResetPayload, Timeout: + lh.illegalLoginCounter = 0 + lh.locked = false + + log.Printf("User '%v' resetted.", lh.userId) + + return "Authenticating", nil + } + + log.Printf("Illegal payload '%v' during state 'authenticating'!", c.Payload) + + return "Authenticating", nil +} + +// Handler for state: "Locked". +func (lh *LoginHandler) HandleStateLocked(c *Condition) (string, interface{}) { + switch pld := c.Payload.(type) { + case *LoginPayload: + log.Printf("User '%v' login rejected, user is locked!", lh.userId) + + return "Locked", false + case *ResetPayload, *UnlockPayload, Timeout: + lh.illegalLoginCounter = 0 + lh.locked = false + + log.Printf("User '%v' resetted / unlocked.", lh.userId) + + return "Authenticating", nil + } + + log.Printf("Illegal payload '%v' during state 'loacked'!", c.Payload) + + return "Locked", nil +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglfsm.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglfsm.go new file mode 100644 index 0000000..bf0dc9b --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglfsm.go @@ -0,0 +1,244 @@ +/* + Tideland Common Go Library - Finite State Machine + + Copyright (C) 2010-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + 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 Tideland 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 OWNER 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. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "log" + "reflect" + "strings" + "time" +) + +//-------------------- +// HELPER TYPES +//-------------------- + +// Condition type. +type Condition struct { + Now int64 + Payload interface{} +} + +// Transition type. +type transition struct { + payload interface{} + resultChan chan interface{} +} + +// Timeout type. +type Timeout int64 + +//-------------------- +// FINITE STATE MACHINE +//-------------------- + +// Handler interface. +type Handler interface { + Init() string + Terminate(string, interface{}) string +} + +// State machine type. +type FSM struct { + Handler Handler + handlerValue reflect.Value + handlerFuncs map[string]reflect.Value + state string + transitionChan chan *transition + timeoutChan <-chan int64 +} + +// Create a new finite state machine. +func NewFSM(h Handler, timeout int64) *FSM { + var bufferSize int + + if timeout > 0 { + bufferSize = int(timeout / 1e3) + } else { + bufferSize = 10 + } + + fsm := &FSM{ + Handler: h, + handlerFuncs: make(map[string]reflect.Value), + state: h.Init(), + transitionChan: make(chan *transition, bufferSize), + } + + if timeout > 0 { + fsm.timeoutChan = time.After(timeout) + } + + fsm.analyze() + + go fsm.backend() + + return fsm +} + +// Send a payload to handle and return the result. +func (fsm *FSM) SendWithResult(payload interface{}) interface{} { + t := &transition{payload, make(chan interface{})} + + fsm.transitionChan <- t + + return <-t.resultChan +} + +// Send a payload with no result. +func (fsm *FSM) Send(payload interface{}) { + t := &transition{payload, nil} + + fsm.transitionChan <- t +} + +// Send a payload with no result after a given time. +func (fsm *FSM) SendAfter(payload interface{}, ns int64) { + saf := func() { + time.Sleep(ns) + + fsm.Send(payload) + } + + go saf() +} + +// Return the current state. +func (fsm *FSM) State() string { + return fsm.state +} + +// Return the supervisor. +func (fsm *FSM) Supervisor() *Supervisor { + return GlobalSupervisor() +} + +// Recover after an error. +func (fsm *FSM) Recover(recoverable Recoverable, err interface{}) { + log.Printf("[cgl] recovering finite state machine server backend after error '%v'!", err) + + go fsm.backend() +} + +// Analyze the event handler and prepare the state table. +func (fsm *FSM) analyze() { + prefix := "HandleState" + + fsm.handlerValue = reflect.ValueOf(fsm.Handler) + + num := fsm.handlerValue.Type().NumMethod() + + for i := 0; i < num; i++ { + meth := fsm.handlerValue.Type().Method(i) + + if (meth.PkgPath == "") && (strings.HasPrefix(meth.Name, prefix)) { + if (meth.Type.NumIn() == 2) && (meth.Type.NumOut() == 2) { + state := meth.Name[len(prefix):len(meth.Name)] + + fsm.handlerFuncs[state] = meth.Func + } + } + } +} + +// State machine backend. +func (fsm *FSM) backend() { + defer func() { + HelpIfNeeded(fsm, recover()) + }() + + // Message loop. + + for { + select { + case t := <-fsm.transitionChan: + // Regular transition. + + if nextState, ok := fsm.handle(t); ok { + // Continue. + + fsm.state = nextState + } else { + // Stop processing. + + fsm.state = fsm.Handler.Terminate(fsm.state, nextState) + + return + } + case to := <-fsm.timeoutChan: + // Timeout signal resent to let it be handled. + + t := &transition{Timeout(to), nil} + + fsm.transitionChan <- t + } + } +} + +// Handle a transition. +func (fsm *FSM) handle(t *transition) (string, bool) { + condition := &Condition{time.Nanoseconds(), t.payload} + handlerFunc := fsm.handlerFuncs[fsm.state] + handlerArgs := make([]reflect.Value, 2) + + handlerArgs[0] = fsm.handlerValue + handlerArgs[1] = reflect.ValueOf(condition) + + results := handlerFunc.Call(handlerArgs) + + nextState := results[0].Interface().(string) + result := results[1].Interface() + + // Return a result if wanted. + + if t.resultChan != nil { + t.resultChan <- result + } + + // Check for termination. + + if nextState == "Terminate" { + return nextState, false + } + + return nextState, true +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglmon.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglmon.go new file mode 100644 index 0000000..6747358 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglmon.go @@ -0,0 +1,569 @@ +/* + Tideland Common Go Library - Monitoring + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + 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 Tideland 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 OWNER 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. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "fmt" + "io" + "log" + "os" + "time" +) + +//-------------------- +// GLOBAL VARIABLES +//-------------------- + +var monitor *SystemMonitor + +//-------------------- +// CONSTANTS +//-------------------- + +const ( + etmTLine = "+------------------------------------------+-----------+-----------+-----------+-----------+---------------+-----------+\n" + etmHeader = "| Name | Count | Min Time | Max Time | Avg Time | Total Time | Op/Sec |\n" + etmFormat = "| %-40s | %9d | %9.3f | %9.3f | %9.3f | %13.3f | %9d |\n" + etmFooter = "| All times in milliseconds. |\n" + etmELine = "+----------------------------------------------------------------------------------------------------------------------+\n" + + ssiTLine = "+------------------------------------------+-----------+---------------+---------------+---------------+---------------+\n" + ssiHeader = "| Name | Count | Act Value | Min Value | Max Value | Avg Value |\n" + ssiFormat = "| %-40s | %9d | %13d | %13d | %13d | %13d |\n" + + dsrTLine = "+------------------------------------------+---------------------------------------------------------------------------+\n" + dsrHeader = "| Name | Value |\n" + dsrFormat = "| %-40s | %-73s |\n" +) + +const ( + cmdMeasuringPointsMap = iota + cmdMeasuringPointsDo + cmdStaySetVariablesMap + cmdStaySetVariablesDo + cmdDynamicStatusRetrieversMap + cmdDynamicStatusRetrieversDo +) + +//-------------------- +// MONITORING +//-------------------- + +// Command encapsulated the data for any command. +type command struct { + opCode int + args interface{} + respChan chan interface{} +} + +// The system monitor type. +type SystemMonitor struct { + etmData map[string]*MeasuringPoint + ssiData map[string]*StaySetVariable + dsrData map[string]DynamicStatusRetriever + measuringChan chan *Measuring + valueChan chan *value + retrieverRegistrationChan chan *retrieverRegistration + commandChan chan *command +} + +// Monitor returns the system monitor if it exists. +// Otherwise it creates it first. +func Monitor() *SystemMonitor { + if monitor == nil { + // Create system monitor. + monitor = &SystemMonitor{ + etmData: make(map[string]*MeasuringPoint), + ssiData: make(map[string]*StaySetVariable), + dsrData: make(map[string]DynamicStatusRetriever), + measuringChan: make(chan *Measuring, 1000), + valueChan: make(chan *value, 1000), + retrieverRegistrationChan: make(chan *retrieverRegistration, 10), + commandChan: make(chan *command), + } + + go monitor.backend() + } + + return monitor +} + +// BeginMeasuring starts a new measuring with a given id. +// All measurings with the same id will be aggregated. +func (sm *SystemMonitor) BeginMeasuring(id string) *Measuring { + return &Measuring{sm, id, time.Nanoseconds(), 0} +} + +// Measure the execution of a function. +func (sm *SystemMonitor) Measure(id string, f func()) { + m := sm.BeginMeasuring(id) + + f() + + m.EndMeasuring() +} + +// MeasuringPointsMap performs the function f for all measuring points +// and returns a slice with the return values of the function that are +// not nil. +func (sm *SystemMonitor) MeasuringPointsMap(f func(*MeasuringPoint) interface{}) []interface{} { + cmd := &command{cmdMeasuringPointsMap, f, make(chan interface{})} + + sm.commandChan <- cmd + + resp := <-cmd.respChan + + return resp.([]interface{}) +} + +// MeasuringPointsDo performs the function f for +// all measuring points. +func (sm *SystemMonitor) MeasuringPointsDo(f func(*MeasuringPoint)) { + cmd := &command{cmdMeasuringPointsDo, f, nil} + + sm.commandChan <- cmd +} + +// MeasuringPointsWrite prints the measuring points for which +// the passed function returns true to the passed writer. +func (sm *SystemMonitor) MeasuringPointsWrite(w io.Writer, ff func(*MeasuringPoint) bool) { + pf := func(t int64) float64 { return float64(t) / 1000000.0 } + + fmt.Fprint(w, etmTLine) + fmt.Fprint(w, etmHeader) + fmt.Fprint(w, etmTLine) + + lines := sm.MeasuringPointsMap(func(mp *MeasuringPoint) interface{} { + if ff(mp) { + ops := 1e9 / mp.AvgTime + + return fmt.Sprintf(etmFormat, mp.Id, mp.Count, pf(mp.MinTime), pf(mp.MaxTime), pf(mp.AvgTime), pf(mp.TtlTime), ops) + } + + return nil + }) + + for _, line := range lines { + fmt.Fprint(w, line) + } + + fmt.Fprint(w, etmTLine) + fmt.Fprint(w, etmFooter) + fmt.Fprint(w, etmELine) +} + +// MeasuringPointsPrintAll prints all measuring points +// to STDOUT. +func (sm *SystemMonitor) MeasuringPointsPrintAll() { + sm.MeasuringPointsWrite(os.Stdout, func(mp *MeasuringPoint) bool { return true }) +} + +// SetValue sets a value of a stay-set variable. +func (sm *SystemMonitor) SetValue(id string, v int64) { + sm.valueChan <- &value{id, v} +} + +// StaySetVariablesMap performs the function f for all variables +// and returns a slice with the return values of the function that are +// not nil. +func (sm *SystemMonitor) StaySetVariablesMap(f func(*StaySetVariable) interface{}) []interface{} { + cmd := &command{cmdStaySetVariablesMap, f, make(chan interface{})} + + sm.commandChan <- cmd + + resp := <-cmd.respChan + + return resp.([]interface{}) +} + +// StaySetVariablesDo performs the function f for all +// variables. +func (sm *SystemMonitor) StaySetVariablesDo(f func(*StaySetVariable)) { + cmd := &command{cmdStaySetVariablesDo, f, nil} + + sm.commandChan <- cmd +} + +// StaySetVariablesWrite prints the stay-set variables for which +// the passed function returns true to the passed writer. +func (sm *SystemMonitor) StaySetVariablesWrite(w io.Writer, ff func(*StaySetVariable) bool) { + fmt.Fprint(w, ssiTLine) + fmt.Fprint(w, ssiHeader) + fmt.Fprint(w, ssiTLine) + + lines := sm.StaySetVariablesMap(func(ssv *StaySetVariable) interface{} { + if ff(ssv) { + return fmt.Sprintf(ssiFormat, ssv.Id, ssv.Count, ssv.ActValue, ssv.MinValue, ssv.MaxValue, ssv.AvgValue) + } + + return nil + }) + + for _, line := range lines { + fmt.Fprint(w, line) + } + + fmt.Fprint(w, ssiTLine) +} + +// StaySetVariablesPrintAll prints all stay-set variables +// to STDOUT. +func (sm *SystemMonitor) StaySetVariablesPrintAll() { + sm.StaySetVariablesWrite(os.Stdout, func(ssv *StaySetVariable) bool { return true }) +} + +// Register registers a new dynamic status retriever function. +func (sm *SystemMonitor) Register(id string, rf DynamicStatusRetriever) { + sm.retrieverRegistrationChan <- &retrieverRegistration{id, rf} +} + +// Unregister unregisters a dynamic status retriever function. +func (sm *SystemMonitor) Unregister(id string) { + sm.retrieverRegistrationChan <- &retrieverRegistration{id, nil} +} + +// DynamicStatusValuesMap performs the function f for all status values +// and returns a slice with the return values of the function that are +// not nil. +func (sm *SystemMonitor) DynamicStatusValuesMap(f func(string, string) interface{}) []interface{} { + cmd := &command{cmdDynamicStatusRetrieversMap, f, make(chan interface{})} + + sm.commandChan <- cmd + + resp := <-cmd.respChan + + return resp.([]interface{}) +} + +// DynamicStatusValuesDo performs the function f for all +// status values. +func (sm *SystemMonitor) DynamicStatusValuesDo(f func(string, string)) { + cmd := &command{cmdDynamicStatusRetrieversDo, f, nil} + + sm.commandChan <- cmd +} + +// DynamicStatusValuesWrite prints the status values for which +// the passed function returns true to the passed writer. +func (sm *SystemMonitor) DynamicStatusValuesWrite(w io.Writer, ff func(string, string) bool) { + fmt.Fprint(w, dsrTLine) + fmt.Fprint(w, dsrHeader) + fmt.Fprint(w, dsrTLine) + + lines := sm.DynamicStatusValuesMap(func(id, dsv string) interface{} { + if ff(id, dsv) { + return fmt.Sprintf(dsrFormat, id, dsv) + } + + return nil + }) + + for _, line := range lines { + fmt.Fprint(w, line) + } + + fmt.Fprint(w, dsrTLine) +} + +// DynamicStatusValuesPrintAll prints all status values to STDOUT. +func (sm *SystemMonitor) DynamicStatusValuesPrintAll() { + sm.DynamicStatusValuesWrite(os.Stdout, func(id, dsv string) bool { return true }) +} + +// Return the supervisor. +func (sm *SystemMonitor) Supervisor() *Supervisor { + return GlobalSupervisor() +} + +// Recover after an error. +func (sm *SystemMonitor) Recover(recoverable Recoverable, err interface{}) { + log.Printf("[cgl] recovering system monitor backend after error '%v'!", err) + + go sm.backend() +} + +// Backend of the system monitor. +func (sm *SystemMonitor) backend() { + defer func() { + HelpIfNeeded(sm, recover()) + }() + + for { + select { + case measuring := <-sm.measuringChan: + // Received a new measuring. + if mp, ok := sm.etmData[measuring.id]; ok { + // Measuring point found. + mp.update(measuring) + } else { + // New measuring point. + sm.etmData[measuring.id] = newMeasuringPoint(measuring) + } + case value := <-sm.valueChan: + // Received a new value. + if ssv, ok := sm.ssiData[value.id]; ok { + // Variable found. + ssv.update(value) + } else { + // New stay-set variable. + sm.ssiData[value.id] = newStaySetVariable(value) + } + case registration := <-sm.retrieverRegistrationChan: + // Received a new retriever for registration. + if registration.dsr != nil { + // Register a new retriever. + sm.dsrData[registration.id] = registration.dsr + } else { + // Deregister a retriever. + if dsr, ok := sm.dsrData[registration.id]; ok { + sm.dsrData[registration.id] = dsr, false + } + } + case cmd := <-sm.commandChan: + // Receivedd a command to process. + sm.processCommand(cmd) + } + } +} + +// Process a command. +func (sm *SystemMonitor) processCommand(cmd *command) { + switch cmd.opCode { + case cmdMeasuringPointsMap: + // Map the measuring points. + var resp []interface{} + + f := cmd.args.(func(*MeasuringPoint) interface{}) + + for _, mp := range sm.etmData { + v := f(mp) + + if v != nil { + resp = append(resp, v) + } + } + + cmd.respChan <- resp + case cmdMeasuringPointsDo: + // Iterate over the measurings. + f := cmd.args.(func(*MeasuringPoint)) + + for _, mp := range sm.etmData { + f(mp) + } + case cmdStaySetVariablesMap: + // Map the stay-set variables. + var resp []interface{} + + f := cmd.args.(func(*StaySetVariable) interface{}) + + for _, ssv := range sm.ssiData { + v := f(ssv) + + if v != nil { + resp = append(resp, v) + } + } + + cmd.respChan <- resp + case cmdStaySetVariablesDo: + // Iterate over the stay-set variables. + f := cmd.args.(func(*StaySetVariable)) + + for _, ssv := range sm.ssiData { + f(ssv) + } + case cmdDynamicStatusRetrieversMap: + // Map the return values of the dynamic status + // retriever functions. + var resp []interface{} + + f := cmd.args.(func(string, string) interface{}) + + for id, dsr := range sm.dsrData { + dsv := dsr() + v := f(id, dsv) + + if v != nil { + resp = append(resp, v) + } + } + + cmd.respChan <- resp + case cmdDynamicStatusRetrieversDo: + // Iterate over the return values of the + // dynamic status retriever functions. + f := cmd.args.(func(string, string)) + + for id, dsr := range sm.dsrData { + dsv := dsr() + + f(id, dsv) + } + } +} + +//-------------------- +// ADDITIONAL MEASURING TYPES +//-------------------- + +// Measuring contains one measuring. +type Measuring struct { + systemMonitor *SystemMonitor + id string + startTime int64 + endTime int64 +} + +// EndMEasuring ends a measuring and passes it to the +// measuring server in the background. +func (m *Measuring) EndMeasuring() int64 { + m.endTime = time.Nanoseconds() + + m.systemMonitor.measuringChan <- m + + return m.endTime - m.startTime +} + +// MeasuringPoint contains the cumulated measuring +// data of one measuring point. +type MeasuringPoint struct { + Id string + Count int64 + MinTime int64 + MaxTime int64 + TtlTime int64 + AvgTime int64 +} + +// Create a new measuring point out of a measuring. +func newMeasuringPoint(m *Measuring) *MeasuringPoint { + time := m.endTime - m.startTime + mp := &MeasuringPoint{ + Id: m.id, + Count: 1, + MinTime: time, + MaxTime: time, + TtlTime: time, + AvgTime: time, + } + + return mp +} + +// Update a measuring point with a measuring. +func (mp *MeasuringPoint) update(m *Measuring) { + time := m.endTime - m.startTime + + mp.Count++ + + if mp.MinTime > time { + mp.MinTime = time + } + + if mp.MaxTime < time { + mp.MaxTime = time + } + + mp.TtlTime += time + mp.AvgTime = mp.TtlTime / mp.Count +} + +// New value for a stay-set variable. +type value struct { + id string + value int64 +} + +// StaySetVariable contains the cumulated values +// for one stay-set variable. +type StaySetVariable struct { + Id string + Count int64 + ActValue int64 + MinValue int64 + MaxValue int64 + AvgValue int64 + total int64 +} + +// Create a new stay-set variable out of a value. +func newStaySetVariable(v *value) *StaySetVariable { + ssv := &StaySetVariable{ + Id: v.id, + Count: 1, + ActValue: v.value, + MinValue: v.value, + MaxValue: v.value, + AvgValue: v.value, + } + + return ssv +} + +// Update a stay-set variable with a value. +func (ssv *StaySetVariable) update(v *value) { + ssv.Count++ + + ssv.ActValue = v.value + ssv.total += v.value + + if ssv.MinValue > ssv.ActValue { + ssv.MinValue = ssv.ActValue + } + + if ssv.MaxValue < ssv.ActValue { + ssv.MaxValue = ssv.ActValue + } + + ssv.AvgValue = ssv.total / ssv.Count +} + +// DynamicStatusRetriever is called by the server and +// returns a current status as string. +type DynamicStatusRetriever func() string + +// New registration of a retriever function. +type retrieverRegistration struct { + id string + dsr DynamicStatusRetriever +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsml.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsml.go new file mode 100644 index 0000000..c6e4e01 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsml.go @@ -0,0 +1,490 @@ +/* + Tideland Common Go Library - Simple Markup Language + + Copyright (C) 2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + 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 Tideland 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 OWNER 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. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "bufio" + "bytes" + "fmt" + "io" + "os" + "strings" + "unicode" +) + +//-------------------- +// PROCESSOR +//-------------------- + +// Processor interface. +type Processor interface { + OpenTag(tag []string) + CloseTag(tag []string) + Text(text string) +} + +//-------------------- +// NODE +//-------------------- + +// The node. +type Node interface { + Len() int + ProcessWith(p Processor) +} + +//-------------------- +// TAG NODE +//-------------------- + +// The tag node. +type TagNode struct { + tag []string + children []Node +} + +// Create a new tag node. +func NewTagNode(tag string) *TagNode { + tmp := strings.ToLower(tag) + + if !validIdentifier(tmp) { + return nil + } + + tn := &TagNode{ + tag: strings.Split(tmp, ":"), + children: make([]Node, 0), + } + + return tn +} + +// Append a new tag. +func (tn *TagNode) AppendTag(tag string) *TagNode { + n := NewTagNode(tag) + + if n != nil { + tn.children = append(tn.children, n) + } + + return n +} + +// Append a tag node. +func (tn *TagNode) AppendTagNode(n *TagNode) *TagNode { + tn.children = append(tn.children, n) + + return n +} + +// Append a text node. +func (tn *TagNode) AppendText(text string) *TextNode { + n := NewTextNode(text) + + tn.children = append(tn.children, n) + + return n +} + +// Append a tagged text node. +func (tn *TagNode) AppendTaggedText(tag, text string) *TagNode { + n := NewTagNode(tag) + + if n != nil { + n.AppendText(text) + + tn.children = append(tn.children, n) + } + + return n +} + +// Append a text node. +func (tn *TagNode) AppendTextNode(n *TextNode) *TextNode { + tn.children = append(tn.children, n) + + return n +} + +// Return the len of the tag node (aka number of children). +func (tn *TagNode) Len() int { + return len(tn.children) +} + +// Process the node. +func (tn *TagNode) ProcessWith(p Processor) { + p.OpenTag(tn.tag) + + for _, child := range tn.children { + child.ProcessWith(p) + } + + p.CloseTag(tn.tag) +} + +// Return the node as a string. +func (tn *TagNode) String() string { + buf := bytes.NewBufferString("") + spp := NewSmlWriterProcessor(buf, true) + + tn.ProcessWith(spp) + + return buf.String() +} + +//-------------------- +// TEXT NODE +//-------------------- + +// The text node. +type TextNode struct { + text string +} + +// Create a new text node. +func NewTextNode(text string) *TextNode { + return &TextNode{text} +} + +// Return the len of the text node. +func (tn *TextNode) Len() int { + return len(tn.text) +} + +// Process the node. +func (tn *TextNode) ProcessWith(p Processor) { + p.Text(tn.text) +} + +// Return the node as a string. +func (tn *TextNode) String() string { + return tn.text +} + +//-------------------- +// PRIVATE FUNCTIONS +//-------------------- + +// Check an identifier (tag or id). +func validIdentifier(id string) bool { + for _, c := range id { + if c < 'a' || c > 'z' { + if c < '0' || c > '9' { + if c != '-' && c != ':' { + return false + } + } + } + } + + return true +} + +//-------------------- +// SML READER +//-------------------- + +// Control values. +const ( + ctrlText = iota + ctrlSpace + ctrlOpen + ctrlClose + ctrlEscape + ctrlTag + ctrlEOF + ctrlInvalid +) + +// Node read modes. +const ( + modeInit = iota + modeTag + modeText +) + +// Reader for SML. +type SmlReader struct { + reader *bufio.Reader + index int + root *TagNode + error os.Error +} + +// Create the reader. +func NewSmlReader(reader io.Reader) *SmlReader { + // Init the reader. + + sr := &SmlReader{ + reader: bufio.NewReader(reader), + index: -1, + } + + node, ctrl := sr.readNode() + + switch ctrl { + case ctrlClose: + sr.root = node + sr.error = nil + case ctrlEOF: + msg := fmt.Sprintf("eof too early at index %v", sr.index) + + sr.error = os.NewError(msg) + case ctrlInvalid: + msg := fmt.Sprintf("invalid rune at index %v", sr.index) + + sr.error = os.NewError(msg) + } + + return sr +} + +// Return the root tag node. +func (sr *SmlReader) RootTagNode() (*TagNode, os.Error) { + return sr.root, sr.error +} + +// Read a node. +func (sr *SmlReader) readNode() (*TagNode, int) { + var node *TagNode + var buffer *bytes.Buffer + + mode := modeInit + + for { + rune, ctrl := sr.readRune() + + sr.index++ + + switch mode { + case modeInit: + // Before the first opening bracket. + switch ctrl { + case ctrlEOF: + return nil, ctrlEOF + case ctrlOpen: + mode = modeTag + buffer = bytes.NewBufferString("") + } + case modeTag: + // Reading a tag. + switch ctrl { + case ctrlEOF: + return nil, ctrlEOF + case ctrlTag: + buffer.WriteRune(rune) + case ctrlSpace: + if buffer.Len() == 0 { + return nil, ctrlInvalid + } + + node = NewTagNode(buffer.String()) + buffer = bytes.NewBufferString("") + mode = modeText + case ctrlClose: + if buffer.Len() == 0 { + return nil, ctrlInvalid + } + + node = NewTagNode(buffer.String()) + + return node, ctrlClose + default: + return nil, ctrlInvalid + } + case modeText: + // Reading the text including the subnodes following + // the space after the tag or id. + switch ctrl { + case ctrlEOF: + return nil, ctrlEOF + case ctrlOpen: + text := strings.TrimSpace(buffer.String()) + + if len(text) > 0 { + node.AppendText(text) + } + + buffer = bytes.NewBufferString("") + + sr.reader.UnreadRune() + + subnode, subctrl := sr.readNode() + + if subctrl == ctrlClose { + // Correct closed subnode. + + node.AppendTagNode(subnode) + } else { + // Error while reading the subnode. + + return nil, subctrl + } + case ctrlClose: + text := strings.TrimSpace(buffer.String()) + + if len(text) > 0 { + node.AppendText(text) + } + + return node, ctrlClose + case ctrlEscape: + rune, ctrl = sr.readRune() + + if ctrl == ctrlOpen || ctrl == ctrlClose || ctrl == ctrlEscape { + buffer.WriteRune(rune) + + sr.index++ + } else { + return nil, ctrlInvalid + } + default: + buffer.WriteRune(rune) + } + } + } + + return nil, ctrlEOF +} + +// Read a rune. +func (sr *SmlReader) readRune() (rune, control int) { + var size int + + rune, size, sr.error = sr.reader.ReadRune() + + switch { + case size == 0: + return rune, ctrlEOF + case rune == '{': + return rune, ctrlOpen + case rune == '}': + return rune, ctrlClose + case rune == '^': + return rune, ctrlEscape + case rune >= 'a' && rune <= 'z': + return rune, ctrlTag + case rune >= 'A' && rune <= 'Z': + return rune, ctrlTag + case rune >= '0' && rune <= '9': + return rune, ctrlTag + case rune == '-': + return rune, ctrlTag + case rune == ':': + return rune, ctrlTag + case unicode.IsSpace(rune): + return rune, ctrlSpace + } + + return rune, ctrlText +} + +//-------------------- +// SML WRITER PROCESSOR +//-------------------- + +// Processor for writing SML. +type SmlWriterProcessor struct { + writer *bufio.Writer + prettyPrint bool + indentLevel int +} + +// Create a new SML writer processor. +func NewSmlWriterProcessor(writer io.Writer, prettyPrint bool) *SmlWriterProcessor { + swp := &SmlWriterProcessor{ + writer: bufio.NewWriter(writer), + prettyPrint: prettyPrint, + indentLevel: 0, + } + + return swp +} + +// Open a tag. +func (swp *SmlWriterProcessor) OpenTag(tag []string) { + swp.writeIndent(true) + + swp.writer.WriteString("{") + swp.writer.WriteString(strings.Join(tag, ":")) +} + +// Close a tag. +func (swp *SmlWriterProcessor) CloseTag(tag []string) { + swp.writer.WriteString("}") + + if swp.prettyPrint { + swp.indentLevel-- + } + + swp.writer.Flush() +} + +// Write a text. +func (swp *SmlWriterProcessor) Text(text string) { + ta := strings.Replace(text, "^", "^^", -1) + tb := strings.Replace(ta, "{", "^{", -1) + tc := strings.Replace(tb, "}", "^}", -1) + + swp.writeIndent(false) + + swp.writer.WriteString(tc) +} + +// Write an indent in case of pretty print. +func (swp *SmlWriterProcessor) writeIndent(increase bool) { + if swp.prettyPrint { + if swp.indentLevel > 0 { + swp.writer.WriteString("\n") + } + + for i := 0; i < swp.indentLevel; i++ { + swp.writer.WriteString("\t") + } + + if increase { + swp.indentLevel++ + } + } else { + swp.writer.WriteString(" ") + } +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsmr.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsmr.go new file mode 100644 index 0000000..06f3479 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsmr.go @@ -0,0 +1,408 @@ +/* + Tideland Common Go Library - Sorting and Map/Reduce + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + 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 Tideland 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 OWNER 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. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "hash/adler32" + "sort" +) + +//-------------------- +// CONTROL VALUES +//-------------------- + +// Threshold for switching from parallel to sequential quick sort. +var QuickSortParallelThreshold int = 4095 + +// Threshold for switching from sequential quick sort to insertion sort. +var QuickSortSequentialThreshold int = 63 + +//-------------------- +// HELPING FUNCS +//-------------------- + +// Simple insertion sort for smaller data collections. +func insertionSort(data sort.Interface, lo, hi int) { + for i := lo + 1; i < hi+1; i++ { + for j := i; j > lo && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} + +// Get the median based on Tukey's ninther. +func median(data sort.Interface, lo, hi int) int { + m := (lo + hi) / 2 + d := (hi - lo) / 8 + + // Move median into the middle. + + mot := func(ml, mm, mh int) { + if data.Less(mm, ml) { + data.Swap(mm, ml) + } + if data.Less(mh, mm) { + data.Swap(mh, mm) + } + if data.Less(mm, ml) { + data.Swap(mm, ml) + } + } + + // Get low, middle, and high median. + + if hi-lo > 40 { + mot(lo+d, lo, lo+2*d) + mot(m-d, m, m+d) + mot(hi-d, hi, hi-2*d) + } + + // Get combined median. + + mot(lo, m, hi) + + return m +} + +// Partition the data based on the median. +func partition(data sort.Interface, lo, hi int) (int, int) { + med := median(data, lo, hi) + idx := lo + + data.Swap(med, hi) + + for i := lo; i < hi; i++ { + if data.Less(i, hi) { + data.Swap(i, idx) + + idx++ + } + } + + data.Swap(idx, hi) + + return idx - 1, idx + 1 +} + +// Sequential quicksort using itself recursively. +func sequentialQuickSort(data sort.Interface, lo, hi int) { + if hi-lo > QuickSortSequentialThreshold { + // Use sequential quicksort. + + plo, phi := partition(data, lo, hi) + + sequentialQuickSort(data, lo, plo) + sequentialQuickSort(data, phi, hi) + } else { + // Use insertion sort. + + insertionSort(data, lo, hi) + } +} + +// Parallel quicksort using itself recursively +// and concurrent. +func parallelQuickSort(data sort.Interface, lo, hi int, done chan bool) { + if hi-lo > QuickSortParallelThreshold { + // Parallel QuickSort. + + plo, phi := partition(data, lo, hi) + partDone := make(chan bool) + + go parallelQuickSort(data, lo, plo, partDone) + go parallelQuickSort(data, phi, hi, partDone) + + // Wait for the end of both sorts. + + <-partDone + <-partDone + } else { + // Sequential QuickSort. + + sequentialQuickSort(data, lo, hi) + } + + // Signal that it's done. + + done <- true +} + +//-------------------- +// PARALLEL QUICKSORT +//-------------------- + +func Sort(data sort.Interface) { + done := make(chan bool) + + go parallelQuickSort(data, 0, data.Len()-1, done) + + <-done +} + +//-------------------- +// BASIC KEY/VALUE TYPES +//-------------------- + +// Data processing is based on key/value pairs. +type KeyValue struct { + Key string + Value interface{} +} + +// Channel for the transfer of key/value pairs. +type KeyValueChan chan *KeyValue + +// Slice of key/value channels. +type KeyValueChans []KeyValueChan + +// Map a key/value pair, emit to the channel. +type MapFunc func(*KeyValue, KeyValueChan) + +// Reduce the key/values of the first channel, emit to the second channel. +type ReduceFunc func(KeyValueChan, KeyValueChan) + +// Channel for closing signals. +type SigChan chan bool + +//-------------------- +// HELPING FUNCS +//-------------------- + +// Close given channel after a number of signals. +func closeSignalChannel(kvc KeyValueChan, size int) SigChan { + sigChan := make(SigChan) + + go func() { + ctr := 0 + + for { + <-sigChan + + ctr++ + + if ctr == size { + close(kvc) + + return + } + } + }() + + return sigChan +} + +// Perform the reducing. +func performReducing(mapEmitChan KeyValueChan, reduceFunc ReduceFunc, reduceSize int, reduceEmitChan KeyValueChan) { + // Start a closer for the reduce emit chan. + + sigChan := closeSignalChannel(reduceEmitChan, reduceSize) + + // Start reduce funcs. + + reduceChans := make(KeyValueChans, reduceSize) + + for i := 0; i < reduceSize; i++ { + reduceChans[i] = make(KeyValueChan) + + go func(inChan KeyValueChan) { + reduceFunc(inChan, reduceEmitChan) + + sigChan <- true + }(reduceChans[i]) + } + + // Read map emitted data. + + for kv := range mapEmitChan { + hash := adler32.Checksum([]byte(kv.Key)) + idx := hash % uint32(reduceSize) + + reduceChans[idx] <- kv + } + + // Close reduce channels. + + for _, reduceChan := range reduceChans { + close(reduceChan) + } +} + +// Perform the mapping. +func performMapping(mapInChan KeyValueChan, mapFunc MapFunc, mapSize int, mapEmitChan KeyValueChan) { + // Start a closer for the map emit chan. + + sigChan := closeSignalChannel(mapEmitChan, mapSize) + + // Start mapping goroutines. + + mapChans := make(KeyValueChans, mapSize) + + for i := 0; i < mapSize; i++ { + mapChans[i] = make(KeyValueChan) + + go func(inChan KeyValueChan) { + for kv := range inChan { + mapFunc(kv, mapEmitChan) + } + + sigChan <- true + }(mapChans[i]) + } + + // Dispatch input data to map channels. + + idx := 0 + + for kv := range mapInChan { + mapChans[idx%mapSize] <- kv + + idx++ + } + + // Close mapping channels channel. + + for i := 0; i < mapSize; i++ { + close(mapChans[i]) + } +} + +//-------------------- +// MAP/REDUCE +//-------------------- + +// Simple map/reduce function. +func MapReduce(inChan KeyValueChan, mapFunc MapFunc, mapSize int, reduceFunc ReduceFunc, reduceSize int) KeyValueChan { + mapEmitChan := make(KeyValueChan) + reduceEmitChan := make(KeyValueChan) + + // Perform operations. + + go performReducing(mapEmitChan, reduceFunc, reduceSize, reduceEmitChan) + go performMapping(inChan, mapFunc, mapSize, mapEmitChan) + + return reduceEmitChan +} + +//-------------------- +// RESULT SORTING +//-------------------- + +// Less function for sorting. +type KeyValueLessFunc func(*KeyValue, *KeyValue) bool + +// Sortable set of key/value pairs. +type SortableKeyValueSet struct { + data []*KeyValue + lessFunc KeyValueLessFunc +} + +// Constructor for the sortable set. +func NewSortableKeyValueSet(kvChan KeyValueChan, kvLessFunc KeyValueLessFunc) *SortableKeyValueSet { + s := &SortableKeyValueSet{ + data: make([]*KeyValue, 0, 1024), + lessFunc: kvLessFunc, + } + + for kv := range kvChan { + l := len(s.data) + + if l == cap(s.data) { + tmp := make([]*KeyValue, l, l+1024) + + copy(tmp, s.data) + + s.data = tmp + } + + s.data = s.data[0 : l+1] + s.data[l] = kv + } + + return s +} + +// Sort interface: Return the len of the data. +func (s *SortableKeyValueSet) Len() int { + return len(s.data) +} + +// Sort interface: Return which element is less. +func (s *SortableKeyValueSet) Less(a, b int) bool { + return s.lessFunc(s.data[a], s.data[b]) +} + +// Sort interface: Swap two elements. +func (s *SortableKeyValueSet) Swap(a, b int) { + s.data[a], s.data[b] = s.data[b], s.data[a] +} + +// Return the data using a channel. +func (s *SortableKeyValueSet) DataChan() KeyValueChan { + kvChan := make(KeyValueChan) + + go func() { + for _, kv := range s.data { + kvChan <- kv + } + + close(kvChan) + }() + + return kvChan +} + +// SortedMapReduce performes a map/reduce and sorts the result. +func SortedMapReduce(inChan KeyValueChan, mapFunc MapFunc, mapSize int, reduceFunc ReduceFunc, reduceSize int, lessFunc KeyValueLessFunc) KeyValueChan { + kvChan := MapReduce(inChan, mapFunc, mapSize, reduceFunc, reduceSize) + s := NewSortableKeyValueSet(kvChan, lessFunc) + + Sort(s) + + return s.DataChan() +} + +// KeyLessFunc compares the keys of two key/value +// pairs. It returns true if the key of a is less +// the key of b. +func KeyLessFunc(a *KeyValue, b *KeyValue) bool { + return a.Key < b.Key +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsup.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsup.go new file mode 100644 index 0000000..d6470cd --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cglsup.go @@ -0,0 +1,290 @@ +/* + Tideland Common Go Library - Supervision + + Copyright (C) 2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + 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 Tideland 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 OWNER 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. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "log" + "os" + "time" +) + +//-------------------- +// GLOBAL VARIABLES +//-------------------- + +var supervisor *Supervisor + +//-------------------- +// INIT +//-------------------- + +func init() { + supervisor = NewSupervisor(nil) +} + +//-------------------- +// FUNCTIONS +//-------------------- + +// Return the global supervisor. +func GlobalSupervisor() *Supervisor { + return supervisor +} + +//-------------------- +// RECOVERABLE +//-------------------- + +// The interface for recoverable types. +type Recoverable interface { + Supervisor() *Supervisor + Recover(Recoverable, interface{}) +} + +//-------------------- +// SUPERVISOR +//-------------------- + +// Message: Add a recoverable for mass recovering. +type addRecoverableMsg struct { + id string + r Recoverable +} + +// Message: Cry for help after an error. +type cryForHelpMsg struct { + r Recoverable + err interface{} +} + +// The supervisor itself. +type Supervisor struct { + supervisor *Supervisor + recoverables map[string]Recoverable + addChan chan *addRecoverableMsg + helpChan chan *cryForHelpMsg +} + +// Create a new supervisor. +func NewSupervisor(parent *Supervisor) *Supervisor { + s := &Supervisor{ + supervisor: parent, + recoverables: make(map[string]Recoverable), + addChan: make(chan *addRecoverableMsg), + helpChan: make(chan *cryForHelpMsg), + } + + go s.backend() + + return s +} + +// Add a recoverable for joint restart in case of an error. +func (s *Supervisor) AddRecoverable(id string, r Recoverable) { + s.addChan <- &addRecoverableMsg{id, r} +} + +// Let a recoverable cry for help at its supervisor. +func (s *Supervisor) Help(r Recoverable, err interface{}) { + s.helpChan <- &cryForHelpMsg{r, err} +} + +// Implement Supervisor() of the recoverable interface for the supervisor itself. +func (s *Supervisor) Supervisor() *Supervisor { + return s.supervisor +} + +// Implement Recover() of the recoverable interface for the supervisor itself. +func (s *Supervisor) Recover(r Recoverable, err interface{}) { + if s == r { + go s.backend() + } +} + +// Backend goroutine of the supervisor. +func (s *Supervisor) backend() { + defer func() { + // Test for error and cry for help + // if needed. + HelpIfNeeded(s, recover()) + }() + + // Wait for cries for help. + + for { + select { + case add := <-s.addChan: + s.recoverables[add.id] = add.r + case cfh := <-s.helpChan: + if len(s.recoverables) > 0 { + // Recover all recoverables. + + done := false + + for _, recoverable := range s.recoverables { + recoverable.Recover(recoverable, cfh.err) + + if recoverable == cfh.r { + done = true + } + } + + // Erroreous recoverable is not registered. + + if !done { + cfh.r.Recover(cfh.r, cfh.err) + } + } else { + // Recover the erroreous recoverable. + + cfh.r.Recover(cfh.r, cfh.err) + } + } + } +} + +//-------------------- +// HEARTBEATABLE +//-------------------- + +// The interface for heartbeatable types. +type Heartbeatable interface { + Recoverable + SetHearbeat(*Heartbeat) +} + +//-------------------- +// HEARBEAT +//-------------------- + +// Heartbeat for one recoverable. +type Heartbeat struct { + recoverable Recoverable + ticker *time.Ticker + openTicks int64 + HeartbeatChan chan *Heartbeat + ImAliveChan chan bool +} + +// Create a new heartbeat. +func NewHeartbeat(r Recoverable, ns int64) *Heartbeat { + h := &Heartbeat{ + recoverable: r, + ticker: time.NewTicker(ns), + openTicks: 0, + HeartbeatChan: make(chan *Heartbeat), + ImAliveChan: make(chan bool), + } + + go h.backend() + + return h +} + +// Backend goroutine of the heartbeat. +func (h *Heartbeat) backend() { + for { + select { + case <-h.ticker.C: + // Check open ticks. + if h.openTicks > 0 { + h.recoverBelated() + } else { + h.sendHeartbeat() + } + case <-h.ImAliveChan: + // Reduce number of open ticks. + if h.openTicks > 0 { + h.openTicks-- + } + } + } +} + +// Recover a belated recaverable. +func (h *Heartbeat) recoverBelated() { + err := os.NewError("Belated recoverable!") + + if h.recoverable.Supervisor() != nil { + // Cry for help using the supervisor. + h.recoverable.Supervisor().Help(h.recoverable, err) + } else { + // Recover directly. + h.recoverable.Recover(h.recoverable, err) + } + + h.openTicks = 0 +} + +// Send a heartbeat. +func (h *Heartbeat) sendHeartbeat() { + select { + case h.HeartbeatChan <- h: + break + default: + log.Printf("Heartbeat can't be sent!") + } + + h.openTicks++ +} + +//-------------------- +// CONVENIENCE FUNCTIONS +//-------------------- + +// Tell the supervisor to help if +// the passed error is not nil. +func HelpIfNeeded(r Recoverable, err interface{}) { + // Test for error. + if err != nil { + // Test for configured supervisor. + if r.Supervisor() != nil { + // Cry for help. + r.Supervisor().Help(r, err) + } + } +} + +// Send a heartbeat. +func ImAlive(h *Heartbeat) { + h.ImAliveChan <- true +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgltim.go b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgltim.go new file mode 100644 index 0000000..6764316 --- /dev/null +++ b/eBook/examples/chapter_11/tideland-cgl.googlecode.com/hg/cgltim.go @@ -0,0 +1,316 @@ +/* + Tideland Common Go Library - Time and Crontab + + Copyright (C) 2009-2011 Frank Mueller / Oldenburg / Germany + + Redistribution and use in source and binary forms, with or + 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 Tideland 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 OWNER 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. +*/ + +package cgl + +//-------------------- +// IMPORTS +//-------------------- + +import ( + "log" + "time" +) + +//-------------------- +// DATE AND TIME +//-------------------- + +// Calc nanoseconds from microseconds. +func NsMicroseconds(count int64) int64 { return count * 1e3 } + +// Calc nanoseconds from milliseconds. +func NsMilliseconds(count int64) int64 { return NsMicroseconds(count * 1e3) } + +// Calc nanoseconds from seconds. +func NsSeconds(count int64) int64 { return NsMilliseconds(count * 1e3) } + +// Calc nanoseconds from minutes. +func NsMinutes(count int64) int64 { return NsSeconds(count * 60) } + +// Calc nanoseconds from hours. +func NsHours(count int64) int64 { return NsMinutes(count * 60) } + +// Calc nanoseconds from days. +func NsDays(count int64) int64 { return NsHours(count * 24) } + +// Calc nanoseconds from weeks. +func NsWeeks(count int64) int64 { return NsDays(count * 7) } + +// Test if the year of a time is in a given list. +func YearInList(time *time.Time, years []int64) bool { + for _, year := range years { + if time.Year == year { + return true + } + } + + return false +} + +// Test if a year of a time is in a given range. +func YearInRange(time *time.Time, minYear, maxYear int64) bool { + return (minYear <= time.Year) && (time.Year <= maxYear) +} + +// Test if the month of a time is in a given list. +func MonthInList(time *time.Time, months []int) bool { + return fieldInList(time.Month, months) +} + +// Test if a month of a time is in a given range. +func MonthInRange(time *time.Time, minMonth, maxMonth int) bool { + return fieldInRange(time.Month, minMonth, maxMonth) +} + +// Test if the day of a time is in a given list. +func DayInList(time *time.Time, days []int) bool { + return fieldInList(time.Day, days) +} + +// Test if a day of a time is in a given range. +func DayInRange(time *time.Time, minDay, maxDay int) bool { + return fieldInRange(time.Day, minDay, maxDay) +} + +// Test if the hour of a time is in a given list. +func HourInList(time *time.Time, hours []int) bool { + return fieldInList(time.Hour, hours) +} + +// Test if a hour of a time is in a given range. +func HourInRange(time *time.Time, minHour, maxHour int) bool { + return fieldInRange(time.Hour, minHour, maxHour) +} + +// Test if the minute of a time is in a given list. +func MinuteInList(time *time.Time, minutes []int) bool { + return fieldInList(time.Minute, minutes) +} + +// Test if a minute of a time is in a given range. +func MinuteInRange(time *time.Time, minMinute, maxMinute int) bool { + return fieldInRange(time.Minute, minMinute, maxMinute) +} + +// Test if the second of a time is in a given list. +func SecondInList(time *time.Time, seconds []int) bool { + return fieldInList(time.Second, seconds) +} + +// Test if a second of a time is in a given range. +func SecondInRange(time *time.Time, minSecond, maxSecond int) bool { + return fieldInRange(time.Second, minSecond, maxSecond) +} + +// Test if the weekday of a time is in a given list. +func WeekdayInList(time *time.Time, weekdays []int) bool { + return fieldInList(time.Weekday, weekdays) +} + +// Test if a weekday of a time is in a given range. +func WeekdayInRange(time *time.Time, minWeekday, maxWeekday int) bool { + return fieldInRange(time.Weekday, minWeekday, maxWeekday) +} + +//-------------------- +// JOB +//-------------------- + +// Check function type. +type CheckFunc func(*time.Time) (bool, bool) + +// Tast function type. +type TaskFunc func(string) + +// Job type. +type Job struct { + id string + check CheckFunc + task TaskFunc +} + +// Create a new job. +func NewJob(id string, check CheckFunc, task TaskFunc) *Job { + return &Job{id, check, task} +} + +// Check if the job has to be performed at a given time. +func (job *Job) checkAndPerform(time *time.Time) bool { + perform, delete := job.check(time) + + if perform { + go job.task(job.id) + } + + return perform && delete +} + +//-------------------- +// CRONTAB +//-------------------- + +const ( + opJobAdd = iota + opJobDel + opCrontabStop +) + +// Crontab control type. +type crontabControl struct { + opCode int + args interface{} +} + +// Crontab. +type Crontab struct { + jobs map[string]*Job + control chan *crontabControl + ticker *time.Ticker +} + +// Start a crontab server. +func NewCrontab() *Crontab { + ctb := &Crontab{ + jobs: make(map[string]*Job), + control: make(chan *crontabControl), + ticker: time.NewTicker(1e9), + } + + go ctb.backend() + + return ctb +} + +// Stop the server. +func (ctb *Crontab) Stop() { + ctb.control <- &crontabControl{opCrontabStop, nil} +} + +// Add a job to the server. +func (ctb *Crontab) AddJob(job *Job) { + ctb.control <- &crontabControl{opJobAdd, job} +} + +// Delete a job from the server. +func (ctb *Crontab) DeleteJob(id string) { + ctb.control <- &crontabControl{opJobDel, id} +} + +// Return the supervisor. +func (src *Crontab) Supervisor() *Supervisor { + return GlobalSupervisor() +} + +// Recover after an error. +func (ctb *Crontab) Recover(recoverable Recoverable, err interface{}) { + log.Printf("Recovering crontab backend after error '%v'!", err) + + go ctb.backend() +} + +// Crontab backend. +func (ctb *Crontab) backend() { + defer func() { + HelpIfNeeded(ctb, recover()) + }() + + for { + select { + case sc := <-ctb.control: + // Control the server. + + switch sc.opCode { + case opJobAdd: + job := sc.args.(*Job) + ctb.jobs[job.id] = job + case opJobDel: + id := sc.args.(string) + job, _ := ctb.jobs[id] + ctb.jobs[id] = job, false + case opCrontabStop: + ctb.ticker.Stop() + } + case <-ctb.ticker.C: + // One tick every second. + + ctb.tick() + } + } +} + +// Handle one server tick. +func (ctb *Crontab) tick() { + now := time.UTC() + deletes := make(map[string]*Job) + + // Check and perform jobs. + + for id, job := range ctb.jobs { + delete := job.checkAndPerform(now) + + if delete { + deletes[id] = job + } + } + + // Delete those marked for deletion. + + for id, job := range deletes { + ctb.jobs[id] = job, false + } +} + +//-------------------- +// HELPERS +//-------------------- + +// Test if an int is in a list of ints. +func fieldInList(field int, list []int) bool { + for _, item := range list { + if field == item { + return true + } + } + + return false +} + +// Test if an int is in a given range. +func fieldInRange(field int, min, max int) bool { + return (min <= field) && (field <= max) +} + +/* + EOF +*/ diff --git a/eBook/examples/chapter_11/type_interfaces.go b/eBook/examples/chapter_11/type_interfaces.go new file mode 100644 index 0000000..9042428 --- /dev/null +++ b/eBook/examples/chapter_11/type_interfaces.go @@ -0,0 +1,62 @@ +package main + +import ( + "fmt" + "math" +) + +type Square struct { + side float32 +} + +type Circle struct { + radius float32 +} + +type Shaper interface { + Area() float32 +} + +func main() { + var areaIntf Shaper + sq1 := new(Square) + sq1.side = 5 + + areaIntf = sq1 + // Is Square the type of areaIntf ? + if t, ok := areaIntf.(*Square); ok { + fmt.Printf("The type of areaIntf is: %T\n", t) + } + if u, ok := areaIntf.(*Circle); ok { + fmt.Printf("The type of areaIntf is: %T\n", u) + } else { + fmt.Println("areaIntf does not contain a variable of type Circle") + } + // testing with switch: + switch t := areaIntf.(type) { + case *Square: + fmt.Printf("Type Square %T with value %v\n", t, t) + case *Circle: + fmt.Printf("Type Circle %T with value %v\n", t, t) + /* + case bool: + fmt.Printf("Type boolean %t\n", t) + case int: + fmt.Printf("Type int %d\n", t) + case *bool: + fmt.Printf("Type pointer to boolean %t\n", *t) + case *int: + fmt.Printf("Type pointer to int %d\n", *t) + */ + default: + fmt.Printf("Unexpected type %T", t) + } +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +func (ci *Circle) Area() float32 { + return ci.radius * ci.radius * math.Pi +} diff --git a/eBook/examples/chapter_12/cat.go b/eBook/examples/chapter_12/cat.go new file mode 100644 index 0000000..2e2abe7 --- /dev/null +++ b/eBook/examples/chapter_12/cat.go @@ -0,0 +1,36 @@ +package main + +import ( + "os" + "io" + "fmt" + "bufio" + "flag" +) + +func cat(r *bufio.Reader) { + for { + buf, err := r.ReadBytes('\n') + if err == io.EOF { + break + } + fmt.Fprintf(os.Stdout, "%s", buf) + } + return +} + +func main() { + flag.Parse() + if flag.NArg() == 0 { + cat(bufio.NewReader(os.Stdin)) + } + for i := 0; i < flag.NArg(); i++ { + f, err := os.Open(flag.Arg(i)) + if err != nil { + fmt.Fprintf(os.Stderr, "%s:error reading from %s: %s\n", os.Args[0], flag.Arg(i), err.Error()) + continue + } + cat(bufio.NewReader(f)) + } +} + diff --git a/eBook/examples/chapter_12/cat2.go b/eBook/examples/chapter_12/cat2.go new file mode 100644 index 0000000..8bb2538 --- /dev/null +++ b/eBook/examples/chapter_12/cat2.go @@ -0,0 +1,41 @@ +package main + +import ( + "flag" + "fmt" + "os" +) + +func cat(f *os.File) { + const NBUF = 512 + var buf [NBUF]byte + for { + switch nr, err := f.Read(buf[:]); true { + case nr < 0: + fmt.Fprintf(os.Stderr, "cat: error reading: %s\n", err.Error()) + os.Exit(1) + case nr == 0: // EOF + return + case nr > 0: + if nw, ew := os.Stdout.Write(buf[0:nr]); nw != nr { + fmt.Fprintf(os.Stderr, "cat: error writing: %s\n", ew.Error()) + } + } + } +} + +func main() { + flag.Parse() // Scans the arg list and sets up flags + if flag.NArg() == 0 { + cat(os.Stdin) + } + for i := 0; i < flag.NArg(); i++ { + f, err := os.Open(flag.Arg(i)) + if f == nil { + fmt.Fprintf(os.Stderr, "cat: can't open %s: error %s\n", flag.Arg(i), err) + os.Exit(1) + } + cat(f) + f.Close() + } +} diff --git a/eBook/examples/chapter_12/echo.go b/eBook/examples/chapter_12/echo.go new file mode 100644 index 0000000..3424772 --- /dev/null +++ b/eBook/examples/chapter_12/echo.go @@ -0,0 +1,29 @@ +package main + +import ( + "os" + "flag" // command line option parser +) + +var NewLine = flag.Bool("n", false, "print newline") // echo -n flag, of type *bool + +const ( + Space = " " + Newline = "\n" +) + +func main() { + flag.PrintDefaults() + flag.Parse() // Scans the arg list and sets up flags + var s string = "" + for i := 0; i < flag.NArg(); i++ { + if i > 0 { + s += " " + if *NewLine { // -n is parsed, flag becomes true + s += Newline + } + } + s += flag.Arg(i) + } + os.Stdout.WriteString(s) +} diff --git a/eBook/examples/chapter_12/filecopy.go b/eBook/examples/chapter_12/filecopy.go new file mode 100644 index 0000000..2cad9af --- /dev/null +++ b/eBook/examples/chapter_12/filecopy.go @@ -0,0 +1,29 @@ +// filecopy.go +package main + +import ( + "fmt" + "io" + "os" +) + +func main() { + CopyFile("target.txt", "source.txt") + fmt.Println("Copy done!") +} + +func CopyFile(dstName, srcName string) (written int64, err error) { + src, err := os.Open(srcName) + if err != nil { + return + } + defer src.Close() + + dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + return + } + defer dst.Close() + + return io.Copy(dst, src) +} diff --git a/eBook/examples/chapter_12/fileinput.go b/eBook/examples/chapter_12/fileinput.go new file mode 100644 index 0000000..d7644d0 --- /dev/null +++ b/eBook/examples/chapter_12/fileinput.go @@ -0,0 +1,34 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "os" +) + +func main() { + // var inputFile *os.File + // var inputError, readerError os.Error + // var inputReader *bufio.Reader + // var inputString string + + inputFile, inputError := os.Open("input.dat") + if inputError != nil { + fmt.Printf("An error occurred on opening the inputfile\n" + + "Does the file exist?\n" + + "Have you got acces to it?\n") + return // exit the function on error + } + defer inputFile.Close() + + inputReader := bufio.NewReader(inputFile) + + for { + inputString, readerError := inputReader.ReadString('\n') + if readerError == io.EOF { + return // error or EOF + } + fmt.Printf("The input was: %s", inputString) + } +} diff --git a/eBook/examples/chapter_12/fileoutput.go b/eBook/examples/chapter_12/fileoutput.go new file mode 100644 index 0000000..50c283e --- /dev/null +++ b/eBook/examples/chapter_12/fileoutput.go @@ -0,0 +1,28 @@ +package main + +import ( + "os" + "bufio" + "fmt" +) + +func main () { + // var outputWriter *bufio.Writer + // var outputFile *os.File + // var outputError os.Error + // var outputString string + outputFile, outputError := os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666) + if outputError != nil { + fmt.Printf("An error occurred with file opening or creation\n") + return + } + defer outputFile.Close() + + outputWriter := bufio.NewWriter(outputFile) + outputString := "hello world!\n" + + for i:=0; i<10; i++ { + outputWriter.WriteString(outputString) + } + outputWriter.Flush() +} \ No newline at end of file diff --git a/eBook/examples/chapter_12/filewrite.go b/eBook/examples/chapter_12/filewrite.go new file mode 100644 index 0000000..7863d5e --- /dev/null +++ b/eBook/examples/chapter_12/filewrite.go @@ -0,0 +1,10 @@ +package main + +import "os" + +func main() { + os.Stdout.WriteString("hello, world\n") + f, _ := os.OpenFile("test", os.O_CREATE|os.O_WRONLY, 0) + defer f.Close() + f.WriteString("hello, world in a file\n") +} diff --git a/eBook/examples/chapter_12/gob1.go b/eBook/examples/chapter_12/gob1.go new file mode 100644 index 0000000..918a23d --- /dev/null +++ b/eBook/examples/chapter_12/gob1.go @@ -0,0 +1,41 @@ +// gob1.go +package main + +import ( + "bytes" + "fmt" + "encoding/gob" + "log" +) + +type P struct { + X, Y, Z int + Name string +} + +type Q struct { + X, Y *int32 + Name string +} + +func main() { + // Initialize the encoder and decoder. Normally enc and dec would be + // bound to network connections and the encoder and decoder would + // run in different processes. + var network bytes.Buffer // Stand-in for a network connection + enc := gob.NewEncoder(&network) // Will write to network. + dec := gob.NewDecoder(&network) // Will read from network. + // Encode (send) the value. + err := enc.Encode(P{3, 4, 5, "Pythagoras"}) + if err != nil { + log.Fatal("encode error:", err) + } + // Decode (receive) the value. + var q Q + err = dec.Decode(&q) + if err != nil { + log.Fatal("decode error:", err) + } + fmt.Printf("%q: {%d,%d}\n", q.Name, *q.X, *q.Y) +} +// Output: "Pythagoras": {3,4} diff --git a/eBook/examples/chapter_12/gob2.go b/eBook/examples/chapter_12/gob2.go new file mode 100644 index 0000000..217e161 --- /dev/null +++ b/eBook/examples/chapter_12/gob2.go @@ -0,0 +1,39 @@ +// gob2.go +package main + +import ( + "encoding/gob" + "log" + "os" +) + +type Address struct { + Type string + City string + Country string +} + +type VCard struct { + FirstName string + LastName string + Addresses []*Address + Remark string +} + +var content string + +func main() { + pa := &Address{"private", "Aartselaar","Belgium"} + wa := &Address{"work", "Boom", "Belgium"} + vc := VCard{"Jan", "Kersschot", []*Address{pa,wa}, "none"} + // fmt.Printf("%v: \n", vc) // {Jan Kersschot [0x126d2b80 0x126d2be0] none}: + // using an encoder: + file, _ := os.OpenFile("vcard.gob", os.O_CREATE|os.O_WRONLY, 0) + defer file.Close() + enc := gob.NewEncoder(file) + err := enc.Encode(vc) + if err != nil { + log.Println("Error in encoding gob") + } +} + diff --git a/eBook/examples/chapter_12/gzipped.go b/eBook/examples/chapter_12/gzipped.go new file mode 100644 index 0000000..2666f43 --- /dev/null +++ b/eBook/examples/chapter_12/gzipped.go @@ -0,0 +1,35 @@ +// gzipped.go +package main + +import ( + "fmt" + "bufio" + "os" + "compress/gzip" +) + +func main() { + fName := "MyFile.gz" + var r *bufio.Reader + fi, err := os.Open(fName) + if err != nil { + fmt.Fprintf(os.Stderr, "%v, Can't open %s: error: %s\n", os.Args[0], fName, + err) + os.Exit(1) + } + fz, err := gzip.NewReader(fi) + if err != nil { + r = bufio.NewReader(fi) + } else { + r = bufio.NewReader(fz) + } + + for { + line, err := r.ReadString('\n') + if err != nil { + fmt.Println("Done reading file") + os.Exit(0) + } + fmt.Println(line) + } +} diff --git a/eBook/examples/chapter_12/hash_sha1.go b/eBook/examples/chapter_12/hash_sha1.go new file mode 100644 index 0000000..d22c8ae --- /dev/null +++ b/eBook/examples/chapter_12/hash_sha1.go @@ -0,0 +1,31 @@ +// hash_sha1.go +package main + +import ( + "fmt" + "crypto/sha1" + "io" + "log" +) + +func main() { + hasher := sha1.New() + io.WriteString(hasher, "test") + b := []byte{} + fmt.Printf("Result: %x\n", hasher.Sum(b)) + fmt.Printf("Result: %d\n", hasher.Sum(b)) + // + hasher.Reset() + data := []byte("We shall overcome!") + n, err := hasher.Write(data) + if n!=len(data) || err!=nil { + log.Printf("Hash write error: %v / %v", n, err) + } + checksum := hasher.Sum(b) + fmt.Printf("Result: %x\n", checksum) +} +/* Output: +Result: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 +Result: [169 74 143 229 204 177 155 166 28 76 8 115 211 145 233 135 152 47 187 211] +Result: e2222bfc59850bbb00a722e764a555603bb59b2a +*/ diff --git a/eBook/examples/chapter_12/input.dat b/eBook/examples/chapter_12/input.dat new file mode 100644 index 0000000..c19fab2 --- /dev/null +++ b/eBook/examples/chapter_12/input.dat @@ -0,0 +1,5 @@ +chicken +cow +donkey +horse +pig diff --git a/eBook/examples/chapter_12/io_interfaces.go b/eBook/examples/chapter_12/io_interfaces.go new file mode 100644 index 0000000..165d9f1 --- /dev/null +++ b/eBook/examples/chapter_12/io_interfaces.go @@ -0,0 +1,18 @@ +// interfaces being used in the GO-package fmt +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + // unbuffered + fmt.Fprintf(os.Stdout, "%s\n", "hello world! - unbuffered") + // buffered: os.Stdout implements io.Writer + buf := bufio.NewWriter(os.Stdout) + // and now so does buf. + fmt.Fprintf(buf, "%s\n", "hello world! - buffered") + buf.Flush() +} diff --git a/eBook/examples/chapter_12/json.go b/eBook/examples/chapter_12/json.go new file mode 100644 index 0000000..7958148 --- /dev/null +++ b/eBook/examples/chapter_12/json.go @@ -0,0 +1,40 @@ +// json.go.go +package main + +import ( + "fmt" + "encoding/json" + "log" + "os" +) + +type Address struct { + Type string + City string + Country string +} + +type VCard struct { + FirstName string + LastName string + Addresses []*Address + Remark string +} + +func main() { + pa := &Address{"private", "Aartselaar","Belgium"} + wa := &Address{"work", "Boom", "Belgium"} + vc := VCard{"Jan", "Kersschot", []*Address{pa,wa}, "none"} + // fmt.Printf("%v: \n", vc) // {Jan Kersschot [0x126d2b80 0x126d2be0] none}: + // JSON format: + js, _ := json.Marshal(vc) + fmt.Printf("JSON format: %s", js) + // using an encoder: + file, _ := os.OpenFile("vcard.json", os.O_CREATE|os.O_WRONLY, 0) + defer file.Close() + enc := json.NewEncoder(file) + err := enc.Encode(vc) + if err != nil { + log.Println("Error in encoding json") + } +} diff --git a/eBook/examples/chapter_12/json_xml_case.go b/eBook/examples/chapter_12/json_xml_case.go new file mode 100644 index 0000000..9c320e2 --- /dev/null +++ b/eBook/examples/chapter_12/json_xml_case.go @@ -0,0 +1,54 @@ +// json_xml_case.go +package main + +import ( + "encoding/json" + "encoding/xml" + "fmt" + "log" + "strings" +) + +type thing struct { + Field1 int + Field2 string +} + +func main() { + x := `423hello from xml` + j := `{"field1": 423, "field2": "hello from json"}` + + tx := thing{} + if err := xml.Unmarshal(strings.NewReader(x), &tx); err != nil { + log.Fatalf("Error unmarshaling XML: %v", err) + } + + tj := thing{} + if err := json.Unmarshal([]byte(j), &tj); err != nil { + log.Fatalf("Error unmarshaling JSON: %v", err) + } + + fmt.Printf("From JSON: %#v\n", tj) + fmt.Printf("From XML: %#v\n", tx) + +} +/* Output with +type thing struct { + Field1 int + Field2 string +}: + +From XML: main.thing{Field1:0, Field2:""} // All matching is case sensitive! +From JSON: main.thing{Field1:423, Field2:"hello from json"} + +Output with +type thing struct { + field1 int + field2 string +}: + +2012/02/22 10:51:11 Error unmarshaling JSON: json: cannot unmarshal object +field1" into unexported field field1 of type main.thing + +JSON uses reflection to unmarshal! +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_12/os_args.go b/eBook/examples/chapter_12/os_args.go new file mode 100644 index 0000000..7dc9aa9 --- /dev/null +++ b/eBook/examples/chapter_12/os_args.go @@ -0,0 +1,16 @@ +// os_args.go +package main + +import ( + "fmt" + "os" + "strings" +) + +func main() { + who := "Alice " + if len(os.Args) > 1 { + who += strings.Join(os.Args[1:], " ") + } + fmt.Println("Good Morning", who) +} diff --git a/eBook/examples/chapter_12/output.dat b/eBook/examples/chapter_12/output.dat new file mode 100644 index 0000000..8ee7109 --- /dev/null +++ b/eBook/examples/chapter_12/output.dat @@ -0,0 +1,10 @@ +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! +hello world! diff --git a/eBook/examples/chapter_12/products.txt b/eBook/examples/chapter_12/products.txt new file mode 100644 index 0000000..9609c62 --- /dev/null +++ b/eBook/examples/chapter_12/products.txt @@ -0,0 +1,3 @@ +ABC|The ABC of Ruby|40 +FUNC|Functional languages|56 +GO|The Go Way|45 diff --git a/eBook/examples/chapter_12/products2.txt b/eBook/examples/chapter_12/products2.txt new file mode 100644 index 0000000..e5886d4 --- /dev/null +++ b/eBook/examples/chapter_12/products2.txt @@ -0,0 +1,3 @@ +ABC 40 150 +FUNC 56 280 +GO 45 356 diff --git a/eBook/examples/chapter_12/products_copy.txt b/eBook/examples/chapter_12/products_copy.txt new file mode 100644 index 0000000..9609c62 --- /dev/null +++ b/eBook/examples/chapter_12/products_copy.txt @@ -0,0 +1,3 @@ +ABC|The ABC of Ruby|40 +FUNC|Functional languages|56 +GO|The Go Way|45 diff --git a/eBook/examples/chapter_12/read_file2.go b/eBook/examples/chapter_12/read_file2.go new file mode 100644 index 0000000..59e4397 --- /dev/null +++ b/eBook/examples/chapter_12/read_file2.go @@ -0,0 +1,38 @@ +// read_csvfile.go +package main + +import ( + "fmt" + "os" +// "io/ioutil" +// "strings" +) + +func main() { + file, err := os.Open("products2.txt") + if err != nil { + panic(err) + } + defer file.Close() + + var col1, col2, col3 []string + for { + var v1, v2, v3 string + _, err := fmt.Fscanln(file, &v1, &v2, &v3) + if err != nil { + break + } + col1 = append(col1, v1) + col2 = append(col2, v2) + col3 = append(col3, v3) + } + + fmt.Println(col1) + fmt.Println(col2) + fmt.Println(col3) +} +/* Output: +[ABC FUNC GO] +[40 56 45] +[150 280 356] +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_12/read_files.go b/eBook/examples/chapter_12/read_files.go new file mode 100644 index 0000000..2c37e95 --- /dev/null +++ b/eBook/examples/chapter_12/read_files.go @@ -0,0 +1,30 @@ +// read_files.go +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "os" +) + +func main() { + fmt.Printf("Reading files...\n") + flag.Parse() + + for i := 0; i < flag.NArg(); i++ { + fmt.Printf("[File: %v]\n", flag.Arg(i)) + fin, err := os.Open(flag.Arg(i)) + if err != nil { + fmt.Printf("The file %v does not exist!\n", flag.Arg(i)) + break + } + r := bufio.NewReader(fin) + for line, _, err := r.ReadLine(); + err != io.EOF; + line, _, err = r.ReadLine() { + fmt.Printf("Lines: %v (error %v)\n", string(line), err) + } + } +} diff --git a/eBook/examples/chapter_12/read_write_file1.go b/eBook/examples/chapter_12/read_write_file1.go new file mode 100644 index 0000000..57314a5 --- /dev/null +++ b/eBook/examples/chapter_12/read_write_file1.go @@ -0,0 +1,21 @@ +// read_write_file.go +package main + +import ( + "fmt" + "io/ioutil" +) + +func main() { + inputFile := "products.txt" + outputFile := "products_copy.txt" + buf, err := ioutil.ReadFile(inputFile) + if err != nil { + panic(err.Error()) + } + fmt.Printf("%s\n", string(buf)) + err = ioutil.WriteFile(outputFile, buf, 0x644) + if err != nil { + panic(err.Error()) + } +} diff --git a/eBook/examples/chapter_12/readinput1.go b/eBook/examples/chapter_12/readinput1.go new file mode 100644 index 0000000..175401c --- /dev/null +++ b/eBook/examples/chapter_12/readinput1.go @@ -0,0 +1,24 @@ +// read input from the console: +package main + +import ( + "fmt" +) + +var ( + firstName, lastName, s string + i int + f float32 + input = "56.12 / 5212 / Go" + format = "%f / %d / %s" +) + +func main() { + fmt.Println("Please enter your full name: ") + fmt.Scanln(&firstName, &lastName) + // fmt.Scanf("%s %s", &firstName, &lastName) + fmt.Printf("Hi %s %s!\n", firstName, lastName) // Hi Chris Naegels + + fmt.Sscanf(input, format, &f, &i, &s) + fmt.Println("From the string we read: ", f, i, s) // From the string we read: 56.12 5212 Go +} diff --git a/eBook/examples/chapter_12/readinput2.go b/eBook/examples/chapter_12/readinput2.go new file mode 100644 index 0000000..21be89a --- /dev/null +++ b/eBook/examples/chapter_12/readinput2.go @@ -0,0 +1,22 @@ +// read input from the console: +package main + +import ( + "fmt" + "bufio" + "os" +) + +var inputReader *bufio.Reader + var input string + var err error + +func main() { + inputReader = bufio.NewReader(os.Stdin) // reader for input + fmt.Println("Please enter some input: ") + input, err = inputReader.ReadString('\n') + + if err == nil { + fmt.Printf("The input was: %s\n", input) + } +} diff --git a/eBook/examples/chapter_12/source.txt b/eBook/examples/chapter_12/source.txt new file mode 100644 index 0000000..9609c62 --- /dev/null +++ b/eBook/examples/chapter_12/source.txt @@ -0,0 +1,3 @@ +ABC|The ABC of Ruby|40 +FUNC|Functional languages|56 +GO|The Go Way|45 diff --git a/eBook/examples/chapter_12/switch_input.go b/eBook/examples/chapter_12/switch_input.go new file mode 100644 index 0000000..99e606b --- /dev/null +++ b/eBook/examples/chapter_12/switch_input.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "os" + "bufio" +) + +func main() { + inputReader := bufio.NewReader(os.Stdin) + fmt.Println("Please enter your name:") + input, err := inputReader.ReadString('\n') + + if err != nil { + fmt.Println("There were errors reading, exiting program.") + return + } + + fmt.Printf("Your name is %s", input) + // For Unix: test with delimiter "\n", for Windows: test with "\r\n" + switch input { + case "Philip\r\n": fmt.Println("Welcome Philip!") + case "Chris\r\n": fmt.Println("Welcome Chris!") + case "Ivo\r\n": fmt.Println("Welcome Ivo!") + default: fmt.Printf("You are not welcome here! Goodbye!") + } + + // version 2: + switch input { + case "Philip\r\n": fallthrough + case "Ivo\r\n": fallthrough + case "Chris\r\n": fmt.Printf("Welcome %s\n", input) + default: fmt.Printf("You are not welcome here! Goodbye!\n") + } + + // version 3: + switch input { + case "Philip\r\n", "Ivo\r\n": fmt.Printf("Welcome %s\n", input) + default: fmt.Printf("You are not welcome here! Goodbye!\n") + } +} diff --git a/eBook/examples/chapter_12/target.txt b/eBook/examples/chapter_12/target.txt new file mode 100644 index 0000000..9609c62 --- /dev/null +++ b/eBook/examples/chapter_12/target.txt @@ -0,0 +1,3 @@ +ABC|The ABC of Ruby|40 +FUNC|Functional languages|56 +GO|The Go Way|45 diff --git a/eBook/examples/chapter_12/test b/eBook/examples/chapter_12/test new file mode 100644 index 0000000..6f2c2db --- /dev/null +++ b/eBook/examples/chapter_12/test @@ -0,0 +1 @@ +hello, world in a file diff --git a/eBook/examples/chapter_12/vcard.gob b/eBook/examples/chapter_12/vcard.gob new file mode 100644 index 0000000000000000000000000000000000000000..fafd3849c14b900773ae4749e32a8c32d1b5741b GIT binary patch literal 228 zcmYk0-Acni6ok(t(HIeY10SFlzC#ia(IO(!8}Z^`4!W4#EoZluURr-%dz*wpdp9$D z%*<{2&ViFf%i1Ar2?eSfqai-96jhBO4TQ6wjOG)LpbDZpM+a^(z;3)I^VIi~Noqs(aB8-adRphH|Oq hi=*JYW{p95W<}XZ|87=xxV`qnk)rY59;ePbp&eo|KimKS literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_12/vcard.json b/eBook/examples/chapter_12/vcard.json new file mode 100644 index 0000000..91d0da3 --- /dev/null +++ b/eBook/examples/chapter_12/vcard.json @@ -0,0 +1 @@ +{"FirstName":"Jan","LastName":"Kersschot","Addresses":[{"Type":"private","City":"Aartselaar","Country":"Belgium"},{"Type":"work","City":"Boom","Country":"Belgium"}],"Remark":"none"} diff --git a/eBook/examples/chapter_12/xml.go b/eBook/examples/chapter_12/xml.go new file mode 100644 index 0000000..0082aab --- /dev/null +++ b/eBook/examples/chapter_12/xml.go @@ -0,0 +1,49 @@ +// xml.go +package main + +import ( + "fmt" + "strings" + "encoding/xml" +) + +var t, token xml.Token +var err error + +func main() { + input := "LauraLynn" + inputReader := strings.NewReader(input) + p := xml.NewDecoder(inputReader) + + for t, err = p.Token(); err == nil; t, err = p.Token() { + switch token := t.(type) { + case xml.StartElement: + name := token.Name.Local + fmt.Printf("Token name: %s\n", name) + for _, attr := range token.Attr { + attrName := attr.Name.Local + attrValue := attr.Value + fmt.Printf("An attribute is: %s %s\n", attrName, attrValue) + // ... + } + case xml.EndElement: + fmt.Println("End of token") + case xml.CharData: + content := string([]byte(token)) + fmt.Printf("This is the content: %v\n", content ) + // ... + default: + // ... + } + } +} +/* Output: +Token name: Person +Token name: FirstName +This is the content: Laura +End of token +Token name: LastName +This is the content: Lynn +End of token +End of token +*/ diff --git a/eBook/examples/chapter_13/errors.go b/eBook/examples/chapter_13/errors.go new file mode 100644 index 0000000..442c2bc --- /dev/null +++ b/eBook/examples/chapter_13/errors.go @@ -0,0 +1,14 @@ +// errors.go +package main + +import ( + "errors" + "fmt" +) + +var errNotFound error = errors.New("Not found error") + +func main() { + fmt.Printf("error: %v", errNotFound) +} +// error: Not found error \ No newline at end of file diff --git a/eBook/examples/chapter_13/even/even/even.go b/eBook/examples/chapter_13/even/even/even.go new file mode 100644 index 0000000..204c443 --- /dev/null +++ b/eBook/examples/chapter_13/even/even/even.go @@ -0,0 +1,10 @@ +// even.go +package even + +func Even(i int) bool { // Exported function + return i%2 == 0 +} + +func Odd(i int) bool { // Exported function + return i%2 != 0 +} diff --git a/eBook/examples/chapter_13/even/even/oddeven_test.go b/eBook/examples/chapter_13/even/even/oddeven_test.go new file mode 100644 index 0000000..0afd978 --- /dev/null +++ b/eBook/examples/chapter_13/even/even/oddeven_test.go @@ -0,0 +1,27 @@ +// oddeven_test.go +package even + +import "testing" + +func TestEven(t *testing.T) { + if !Even(10) { + t.Log(" 10 must be even!") + t.Fail() + } + if Even(7) { + t.Log(" 7 is not even!") + t.Fail() + } + +} + +func TestOdd(t *testing.T) { + if !Odd(11) { + t.Log(" 11 must be odd!") + t.Fail() + } + if Odd(10) { + t.Log(" 10 is not odd!") + t.Fail() + } +} \ No newline at end of file diff --git a/eBook/examples/chapter_13/even/even_main/even_main.go b/eBook/examples/chapter_13/even/even_main/even_main.go new file mode 100644 index 0000000..bf9dd88 --- /dev/null +++ b/eBook/examples/chapter_13/even/even_main/even_main.go @@ -0,0 +1,13 @@ +// test_oddeven.go +package main + +import ( + "fmt" + "even/even" +) + +func main() { + for i:=0; i<=100; i++ { + fmt.Printf("Is the integer %d even? %v\n", i, even.Even(i)) + } +} diff --git a/eBook/examples/chapter_13/exec.go b/eBook/examples/chapter_13/exec.go new file mode 100644 index 0000000..c81f6e1 --- /dev/null +++ b/eBook/examples/chapter_13/exec.go @@ -0,0 +1,61 @@ +// exec.go +package main +import ( + "fmt" + "os/exec" + "os" +) + +func main() { +// 1) os.StartProcess // +/*********************/ +/* Linux: */ + env := os.Environ() + procAttr := &os.ProcAttr{ + Env: env, + Files: []*os.File{ + os.Stdin, + os.Stdout, + os.Stderr, + }, + } + // 1st example: list files + pid, err := os.StartProcess("/bin/ls", []string{"ls", "-l"}, procAttr) + if err != nil { + fmt.Printf("Error %v starting process!", err) // + os.Exit(1) + } + fmt.Printf("The process id is %v", pid) + // 2nd example: show all processes + pid, err = os.StartProcess("/bin/ps", []string{"-e", "-opid,ppid,comm"}, procAttr) + if err != nil { + fmt.Printf("Error %v starting process!", err) // + os.Exit(1) + } + fmt.Printf("The process id is %v", pid) +/* Output 1st: +The process id is &{2054 0}total 2056 +-rwxr-xr-x 1 ivo ivo 1157555 2011-07-04 16:48 Mieken_exec +-rw-r--r-- 1 ivo ivo 2124 2011-07-04 16:48 Mieken_exec.go +-rw-r--r-- 1 ivo ivo 18528 2011-07-04 16:48 Mieken_exec_go_.6 +-rwxr-xr-x 1 ivo ivo 913920 2011-06-03 16:13 panic.exe +-rw-r--r-- 1 ivo ivo 180 2011-04-11 20:39 panic.go +*/ + +// 2) exec.Run // +/***************/ +// Linux: OK, but not for ls ? +// cmd := exec.Command("ls", "-l") // no error, but doesn't show anything ? +// cmd := exec.Command("ls") // no error, but doesn't show anything ? + cmd := exec.Command("gedit") // this opens a gedit-window + err = cmd.Run() + if err != nil { + fmt.Printf("Error %v executing command!", err) + os.Exit(1) + } + fmt.Printf("The command is %v", cmd) +// The command is &{/bin/ls [ls -l] [] 0xf840000210 true [0xf84000ea50 0xf84000e9f0 0xf84000e9c0] [0xf84000ea50 0xf84000e9f0 0xf84000e9c0] [] [] 0xf8400128c0} +} +// in Windows: uitvoering: Error fork/exec /bin/ls: The system cannot find the path specified. starting process! + + diff --git a/eBook/examples/chapter_13/panic.go b/eBook/examples/chapter_13/panic.go new file mode 100644 index 0000000..139c62f --- /dev/null +++ b/eBook/examples/chapter_13/panic.go @@ -0,0 +1,9 @@ +package main + +import "fmt" + +func main() { + fmt.Println("Starting the program") + panic("A severe error occurred: stopping the program!") + fmt.Println("Ending the program") +} \ No newline at end of file diff --git a/eBook/examples/chapter_13/panic_package.go b/eBook/examples/chapter_13/panic_package.go new file mode 100644 index 0000000..8368875 --- /dev/null +++ b/eBook/examples/chapter_13/panic_package.go @@ -0,0 +1,39 @@ +// panic_package.go +package main + +import ( + "fmt" + "./parse/parse" +) + +func main() { + var examples = []string{ + "1 2 3 4 5", + "100 50 25 12.5 6.25", + "2 + 2 = 4", + "1st class", + "", + } + + for _, ex := range examples { + fmt.Printf("Parsing %q:\n ", ex) + nums, err := parse.Parse(ex) + if err != nil { + fmt.Println(err) // here String() method from ParseError is used + continue + } + fmt.Println(nums) + } +} +/* Output: +Parsing "1 2 3 4 5": + [1 2 3 4 5] +Parsing "100 50 25 12.5 6.25": + pkg parse: error parsing "12.5" as int +Parsing "2 + 2 = 4": + pkg parse: error parsing "+" as int +Parsing "1st class": + pkg parse: error parsing "1st" as int +Parsing "": + pkg: no words to parse +*/ diff --git a/eBook/examples/chapter_13/panic_recover.go b/eBook/examples/chapter_13/panic_recover.go new file mode 100644 index 0000000..e743575 --- /dev/null +++ b/eBook/examples/chapter_13/panic_recover.go @@ -0,0 +1,32 @@ +// panic_recover.go +package main + +import ( + "fmt" +) + +func badCall() { + panic("bad end") +} + +func test() { + defer func() { + if e := recover(); e != nil { + fmt.Printf("Panicing %s\r\n", e) + } + }() + badCall() + fmt.Printf("After bad call\r\n") // <-- wordt niet bereikt +} + +func main() { + fmt.Printf("Calling test\r\n") + test() + fmt.Printf("Test completed\r\n") +} + +/* Output: +Calling test +Panicing bad end +Test completed +*/ diff --git a/eBook/examples/chapter_13/parse/parse.go b/eBook/examples/chapter_13/parse/parse.go new file mode 100644 index 0000000..1c81a3c --- /dev/null +++ b/eBook/examples/chapter_13/parse/parse.go @@ -0,0 +1,51 @@ +// parse.go +package parse + +import ( + "fmt" + "strings" + "strconv" +) + +// A ParseError indicates an error in converting a word into an integer. +type ParseError struct { + Index int // The index into the space-separated list of words. + Word string // The word that generated the parse error. + Err error // The raw error that precipitated this error, if any. +} + +// String returns a human-readable error message. +func (e *ParseError) String() string { + return fmt.Sprintf("pkg parse: error parsing %q as int", e.Word) +} + +// Parse parses the space-separated words in in put as integers. +func Parse(input string) (numbers []int, err error) { + defer func() { + if r := recover(); r != nil { + var ok bool + err, ok = r.(error) + if !ok { + err = fmt.Errorf("pkg: %v", r) + } + } + }() + + fields := strings.Fields(input) + numbers = fields2numbers(fields) + return +} + +func fields2numbers(fields []string) (numbers []int) { + if len(fields) == 0 { + panic("no words to parse") + } + for idx, field := range fields { + num, err := strconv.Atoi(field) + if err != nil { + panic(&ParseError{idx, field, err}) + } + numbers = append(numbers, num) + } + return +} diff --git a/eBook/examples/chapter_13/xtime b/eBook/examples/chapter_13/xtime new file mode 100644 index 0000000..8075c1f --- /dev/null +++ b/eBook/examples/chapter_13/xtime @@ -0,0 +1,2 @@ +#!/bin/sh +/usr/bin/time -f '%Uu %Ss %er %MkB %C' "$@" \ No newline at end of file diff --git a/eBook/examples/chapter_14/benchmark_channels.go b/eBook/examples/chapter_14/benchmark_channels.go new file mode 100644 index 0000000..c05a7f5 --- /dev/null +++ b/eBook/examples/chapter_14/benchmark_channels.go @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" + "testing" +) + +func main() { + fmt.Println(" sync", testing.Benchmark(BenchmarkChannelSync).String()) + fmt.Println("buffered", testing.Benchmark(BenchmarkChannelBuffered).String()) +} + +func BenchmarkChannelSync(b *testing.B) { + ch := make(chan int) + go func() { + for i := 0; i < b.N; i++ { + ch <- i + } + close(ch) + }() + for _ = range ch { + } +} + +func BenchmarkChannelBuffered(b *testing.B) { + ch := make(chan int, 128) + go func() { + for i := 0; i < b.N; i++ { + ch <- i + } + close(ch) + }() + for _ = range ch { + } +} diff --git a/eBook/examples/chapter_14/chaining.go b/eBook/examples/chapter_14/chaining.go new file mode 100644 index 0000000..42d595e --- /dev/null +++ b/eBook/examples/chapter_14/chaining.go @@ -0,0 +1,23 @@ +package main + +import ( + "flag" + "fmt" +) + +var ngoroutine = flag.Int("n", 100000, "how many goroutines") + +func f(left, right chan int) { left <- 1+<-right } + +func main() { + flag.Parse() + leftmost := make(chan int) + var left, right chan int = nil, leftmost + for i := 0; i < *ngoroutine; i++ { + left, right = right, make(chan int) + go f(left, right) + } + right <- 0 // bang! + x := <-leftmost // wait for completion + fmt.Println(x) // 100000, ongeveer 1,5 s +} diff --git a/eBook/examples/chapter_14/channel_block.go b/eBook/examples/chapter_14/channel_block.go new file mode 100644 index 0000000..d45d041 --- /dev/null +++ b/eBook/examples/chapter_14/channel_block.go @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func main() { + ch1 := make(chan int) + go pump(ch1) // pump hangs + fmt.Println(<-ch1) // prints only 0 +} + +func pump(ch chan int) { + for i := 0; ; i++ { + ch <- i + } +} + diff --git a/eBook/examples/chapter_14/channel_block2.go b/eBook/examples/chapter_14/channel_block2.go new file mode 100644 index 0000000..eae7239 --- /dev/null +++ b/eBook/examples/chapter_14/channel_block2.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + ch1 := make(chan int) + go pump(ch1) + go suck(ch1) // tons of numbers appear + time.Sleep(1e9) +} + +func pump(ch chan int) { + for i := 0; ; i++ { + ch <- i + } +} + +func suck(ch chan int) { + for { + fmt.Println(<-ch) + } +} diff --git a/eBook/examples/chapter_14/channel_idiom.go b/eBook/examples/chapter_14/channel_idiom.go new file mode 100644 index 0000000..b4aec25 --- /dev/null +++ b/eBook/examples/chapter_14/channel_idiom.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + stream := pump() + go suck(stream) + time.Sleep(1e9) +} + +func pump() chan int { + ch := make(chan int) + go func() { + for i := 0; ; i++ { + ch <- i + } + }() + return ch +} + +func suck(ch chan int) { + for { + fmt.Println(<-ch) + } +} diff --git a/eBook/examples/chapter_14/channel_idiom2.go b/eBook/examples/chapter_14/channel_idiom2.go new file mode 100644 index 0000000..1499008 --- /dev/null +++ b/eBook/examples/chapter_14/channel_idiom2.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + suck(pump()) + time.Sleep(1e9) +} + +func pump() chan int { + ch := make(chan int) + go func() { + for i := 0; ; i++ { + ch <- i + } + }() + return ch +} + +func suck(ch chan int) { + go func() { + for v := range ch { + fmt.Println(v) + } + }() +} diff --git a/eBook/examples/chapter_14/conc_access.go b/eBook/examples/chapter_14/conc_access.go new file mode 100644 index 0000000..3bc20cc --- /dev/null +++ b/eBook/examples/chapter_14/conc_access.go @@ -0,0 +1,54 @@ +// conc_access.go +package main + +import ( + "fmt" + "strconv" +) + +type Person struct { + Name string + salary float64 + chF chan func() +} + +func NewPerson(name string, salary float64) *Person { + p := &Person{name, salary, make(chan func())} + go p.backend() + return p +} + +func (p *Person) backend() { + for f := range p.chF { + f() + } +} + +// Set salary. +func (p *Person) SetSalary(sal float64) { + p.chF <- func() { p.salary = sal } +} + +// Retrieve salary. +func (p *Person) Salary() float64 { + fChan := make(chan float64) + p.chF <- func() { fChan <- p.salary } + return <-fChan +} + +func (p *Person) String() string { + return "Person - name is: " + p.Name + " - salary is: " + strconv.FormatFloat(p.Salary(), 'f', 2, 64) +} + +func main() { + bs := NewPerson("Smith Bill", 2500.5) + fmt.Println(bs) + bs.SetSalary(4000.25) + fmt.Println("Salary changed:") + fmt.Println(bs) +} +/* Output: +Person - name is: Smith Bill - salary is: 2500.50 +Salary changed: +Person - name is: Smith Bill - salary is: 4000.25 +*/ diff --git a/eBook/examples/chapter_14/general_lazy_evalution1.go b/eBook/examples/chapter_14/general_lazy_evalution1.go new file mode 100644 index 0000000..c645b63 --- /dev/null +++ b/eBook/examples/chapter_14/general_lazy_evalution1.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" +) + +type Any interface{} +type EvalFunc func(Any) (Any, Any) + +func main() { + evenFunc := func(state Any) (Any, Any) { + os := state.(int) + ns := os + 2 + return os, ns + } + even := BuildLazyIntEvaluator(evenFunc, 0) + + for i := 0; i < 10; i++ { + fmt.Printf("%vth even: %v\n", i, even()) + } +} + +func BuildLazyEvaluator(evalFunc EvalFunc, initState Any) func() Any { + retValChan := make(chan Any) + loopFunc := func() { + var actState Any = initState + var retVal Any + for { + retVal, actState = evalFunc(actState) + retValChan <- retVal + } + } + retFunc := func() Any { + return <-retValChan + } + go loopFunc() + return retFunc +} + +func BuildLazyIntEvaluator(evalFunc EvalFunc, initState Any) func() int { + ef := BuildLazyEvaluator(evalFunc, initState) + return func() int { + return ef().(int) + } +} +/* Output: +0th even: 0 +1th even: 2 +2th even: 4 +3th even: 6 +4th even: 8 +5th even: 10 +6th even: 12 +7th even: 14 +8th even: 16 +9th even: 18 +*/ diff --git a/eBook/examples/chapter_14/goroutine1.go b/eBook/examples/chapter_14/goroutine1.go new file mode 100644 index 0000000..df3eba5 --- /dev/null +++ b/eBook/examples/chapter_14/goroutine1.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + fmt.Println("In main()") + // longWait() + go longWait() + // shortWait() + go shortWait() + fmt.Println("About to sleep in main()") + time.Sleep(10 * 1e9) // sleep works with a Duration in nanoseconds (ns) ! + fmt.Println("At the end of main()") +} + +func longWait() { + fmt.Println("Beginning longWait()") + time.Sleep(5 * 1e9) // sleep for 5 seconds + fmt.Println("End of longWait()") +} + +func shortWait() { + fmt.Println("Beginning shortWait()") + time.Sleep(2 * 1e9) // sleep for 2 seconds + fmt.Println("End of shortWait()") +} diff --git a/eBook/examples/chapter_14/goroutine2.go b/eBook/examples/chapter_14/goroutine2.go new file mode 100644 index 0000000..f504f8c --- /dev/null +++ b/eBook/examples/chapter_14/goroutine2.go @@ -0,0 +1,33 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + ch := make(chan string) + + go sendData(ch) + go getData(ch) + + time.Sleep(1e9) +} + +func sendData(ch chan string) { + ch <- "Washington" + ch <- "Tripoli" + ch <- "London" + ch <- "Beijing" + ch <- "Tokio" +} + +func getData(ch chan string) { + var input string + // time.Sleep(1e9) + for { + input = <-ch + fmt.Printf("%s ", input) + } +} +// Washington Tripoli London Beijing Tokio \ No newline at end of file diff --git a/eBook/examples/chapter_14/goroutine3.go b/eBook/examples/chapter_14/goroutine3.go new file mode 100644 index 0000000..f827593 --- /dev/null +++ b/eBook/examples/chapter_14/goroutine3.go @@ -0,0 +1,29 @@ +package main + +import "fmt" + +func main() { + ch := make(chan string) + go sendData(ch) + getData(ch) +} + +func sendData(ch chan string) { + ch <- "Washington" + ch <- "Tripoli" + ch <- "London" + ch <- "Beijing" + ch <- "Tokio" + close(ch) +} + +func getData(ch chan string) { + for { + input, open := <-ch + if !open { + break + } + fmt.Printf("%s ", input) + } +} +// Washington Tripoli London Beijing Tokio \ No newline at end of file diff --git a/eBook/examples/chapter_14/goroutine_select.go b/eBook/examples/chapter_14/goroutine_select.go new file mode 100644 index 0000000..b88877f --- /dev/null +++ b/eBook/examples/chapter_14/goroutine_select.go @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + ch1 := make(chan int) + ch2 := make(chan int) + + go pump1(ch1) + go pump2(ch2) + go suck(ch1, ch2) + + time.Sleep(1e9) +} + +func pump1(ch chan int) { + for i := 0; ; i++ { + ch <- i * 2 + } +} + +func pump2(ch chan int) { + for i := 0; ; i++ { + ch <- i + 5 + } +} + +func suck(ch1, ch2 chan int) { + for { + select { + case v := <-ch1: + fmt.Printf("Received on channel 1: %d\n", v) + case v := <-ch2: + fmt.Printf("Received on channel 2: %d\n", v) + } + } +} diff --git a/eBook/examples/chapter_14/goroutine_select2.go b/eBook/examples/chapter_14/goroutine_select2.go new file mode 100644 index 0000000..8adb7c2 --- /dev/null +++ b/eBook/examples/chapter_14/goroutine_select2.go @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" + "time" + "runtime" +) + +func main() { + // setting GOMAXPROCS to 2 gives +- 22% performance increase, + // but increasing the number doesn't increase the performance + // without GOMAXPROCS: +- 86000 + // setting GOMAXPROCS to 2: +- 105000 + // setting GOMAXPROCS to 3: +- 94000 + runtime.GOMAXPROCS(2) + ch1 := make(chan int) + ch2 := make(chan int) + + go pump1(ch1) + go pump2(ch2) + go suck(ch1, ch2) + + time.Sleep(1e9) +} + +func pump1(ch chan int) { + for i:=0; ; i++ { + ch <- i*2 + } +} + +func pump2(ch chan int) { + for i:=0; ; i++ { + ch <- i+5 + } +} + +func suck(ch1,ch2 chan int) { + for i := 0; ; i++ { + select { + case v := <- ch1: + fmt.Printf("%d - Received on channel 1: %d\n", i, v) + case v := <- ch2: + fmt.Printf("%d - Received on channel 2: %d\n", i, v) + } + } +} + + diff --git a/eBook/examples/chapter_14/lazy_evaluation.go b/eBook/examples/chapter_14/lazy_evaluation.go new file mode 100644 index 0000000..f2e2348 --- /dev/null +++ b/eBook/examples/chapter_14/lazy_evaluation.go @@ -0,0 +1,30 @@ +// lazy_evaluation.go +package main + +import ( + "fmt" +) + +var resume chan int + +func integers() chan int { + yield := make (chan int) + count := 0 + go func () { + for { + yield <- count + count++ + } + } () + return yield +} + +func generateInteger() int { + return <-resume +} +func main() { + resume = integers() + fmt.Println(generateInteger()) //=> 0 + fmt.Println(generateInteger()) //=> 1 + fmt.Println(generateInteger()) //=> 2 +} diff --git a/eBook/examples/chapter_14/max_tasks.go b/eBook/examples/chapter_14/max_tasks.go new file mode 100644 index 0000000..6965b32 --- /dev/null +++ b/eBook/examples/chapter_14/max_tasks.go @@ -0,0 +1,31 @@ +package main + +const MAXREQS = 50 +var sem = make(chan int, MAXREQS) + +type Request struct { + a, b int + replyc chan int +} + +func process(r *Request) { + // do something +} + +func handle(r *Request) { + sem <- 1 // doesn't matter what we put in it + process(r) + <-sem // one empty place in the buffer: the next request can start +} + +func server(service chan *Request) { + for { + request := <-service + go handle(request) + } +} + +func main() { + service := make(chan *Request) + go server(service) +} diff --git a/eBook/examples/chapter_14/multiplex_server.go b/eBook/examples/chapter_14/multiplex_server.go new file mode 100644 index 0000000..86e0b37 --- /dev/null +++ b/eBook/examples/chapter_14/multiplex_server.go @@ -0,0 +1,53 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package main + +import "fmt" + +type Request struct { + a, b int + replyc chan int // reply channel inside the Request +} + +type binOp func(a, b int) int + +func run(op binOp, req *Request) { + req.replyc <- op(req.a, req.b) +} + +func server(op binOp, service chan *Request) { + for { + req := <-service // requests arrive here + // start goroutine for request: + go run(op, req) // don't wait for op + } +} + +func startServer(op binOp) chan *Request { + reqChan := make(chan *Request) + go server(op, reqChan) + return reqChan +} + +func main() { + adder := startServer(func(a, b int) int { return a + b }) + const N = 100 + var reqs [N]Request + for i := 0; i < N; i++ { + req := &reqs[i] + req.a = i + req.b = i + N + req.replyc = make(chan int) + adder <- req + } + // checks: + for i := N - 1; i >= 0; i-- { // doesn't matter what order + if <-reqs[i].replyc != N+2*i { + fmt.Println("fail at", i) + } else { + fmt.Println("Request ", i, " is ok!") + } + } + fmt.Println("done") +} diff --git a/eBook/examples/chapter_14/multiplex_server2.go b/eBook/examples/chapter_14/multiplex_server2.go new file mode 100644 index 0000000..49c0823 --- /dev/null +++ b/eBook/examples/chapter_14/multiplex_server2.go @@ -0,0 +1,58 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package main + +import "fmt" + +type Request struct { + a, b int + replyc chan int // reply channel inside the Request +} + +type binOp func(a, b int) int + +func run(op binOp, req *Request) { + req.replyc <- op(req.a, req.b) +} + +func server(op binOp, service chan *Request, quit chan bool) { + for { + select { + case req := <-service: + go run(op, req) + case <-quit: + return + } + } +} + +func startServer(op binOp) (service chan *Request, quit chan bool) { + service = make(chan *Request) + quit = make(chan bool) + go server(op, service, quit) + return service, quit +} + +func main() { + adder, quit := startServer(func(a, b int) int { return a + b }) + const N = 100 + var reqs [N]Request + for i := 0; i < N; i++ { + req := &reqs[i] + req.a = i + req.b = i + N + req.replyc = make(chan int) + adder <- req + } + // checks: + for i := N - 1; i >= 0; i-- { // doesn't matter what order + if <-reqs[i].replyc != N+2*i { + fmt.Println("fail at", i) + } else { + fmt.Println("Request ", i, " is ok!") + } + } + quit <- true + fmt.Println("done") +} diff --git a/eBook/examples/chapter_14/sieve1.go b/eBook/examples/chapter_14/sieve1.go new file mode 100644 index 0000000..184c76e --- /dev/null +++ b/eBook/examples/chapter_14/sieve1.go @@ -0,0 +1,37 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file.package main +package main + +import "fmt" + +// Send the sequence 2, 3, 4, ... to channel 'ch'. +func generate(ch chan int) { + for i := 2; ; i++ { + ch <- i // Send 'i' to channel 'ch'. + } +} + +// Copy the values from channel 'in' to channel 'out', +// removing those divisible by 'prime'. +func filter(in, out chan int, prime int) { + for { + i := <-in // Receive value of new variable 'i' from 'in'. + if i%prime != 0 { + out <- i // Send 'i' to channel 'out'. + } + } +} + +// The prime sieve: Daisy-chain filter processes together. +func main() { + ch := make(chan int) // Create a new channel. + go generate(ch) // Start generate() as a goroutine. + for { + prime := <-ch + fmt.Print(prime, " ") + ch1 := make(chan int) + go filter(ch, ch1, prime) + ch = ch1 + } +} diff --git a/eBook/examples/chapter_14/sieve2.go b/eBook/examples/chapter_14/sieve2.go new file mode 100644 index 0000000..c3e4299 --- /dev/null +++ b/eBook/examples/chapter_14/sieve2.go @@ -0,0 +1,53 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" +) + +// Send the sequence 2, 3, 4, ... to returned channel +func generate() chan int { + ch := make(chan int) + go func() { + for i := 2; ; i++ { + ch <- i + } + }() + return ch +} + +// Filter out input values divisible by 'prime', send rest to returned channel +func filter(in chan int, prime int) chan int { + out := make(chan int) + go func() { + for { + if i := <-in; i%prime != 0 { + out <- i + } + } + }() + return out +} + +func sieve() chan int { + out := make(chan int) + go func() { + ch := generate() + for { + prime := <-ch + ch = filter(ch, prime) + out <- prime + } + }() + return out +} + +func main() { + primes := sieve() + for { + fmt.Println(<-primes) + } +} diff --git a/eBook/examples/chapter_14/timer_goroutine.go b/eBook/examples/chapter_14/timer_goroutine.go new file mode 100644 index 0000000..d9bfb5a --- /dev/null +++ b/eBook/examples/chapter_14/timer_goroutine.go @@ -0,0 +1,42 @@ +// default.go +package main + +import ( + "fmt" + "time" +) + +func main() { + tick := time.Tick(1e8) + boom := time.After(5e8) + for { + select { + case <-tick: + fmt.Println("tick.") + case <-boom: + fmt.Println("BOOM!") + return + default: + fmt.Println(" .") + time.Sleep(5e7) + } + } +} +/* Output: + . + . +tick. + . + . +tick. + . + . +tick. + . + . +tick. + . + . +tick. +BOOM! +*/ diff --git a/eBook/examples/chapter_16/closures_goroutines.go b/eBook/examples/chapter_16/closures_goroutines.go new file mode 100644 index 0000000..7c2fdbe --- /dev/null +++ b/eBook/examples/chapter_16/closures_goroutines.go @@ -0,0 +1,47 @@ +// closures_goroutines.go +package main + +import ( + "fmt" + "time" +) + +var values = [5]int{10, 11, 12, 13, 14} + +func main() { + // version A: + for ix := range values { // ix is index! + func() { + fmt.Print(ix, " ") + }() // call closure, prints each index + } + fmt.Println() + // version B: same as A, but call closure as a goroutine + for ix := range values { + go func() { + fmt.Print(ix, " ") + }() + } + time.Sleep(1e9) + // version C: the right way + for ix := range values { + go func(ix interface{}) { + fmt.Print(ix, " ") + }(ix) + } + time.Sleep(1e9) + // version D: print out the values: + for ix := range values { + val := values[ix] + go func() { + fmt.Print(val, " ") + }() + } + time.Sleep(1e9) +} +/* Output: +0 1 2 3 4 +4 4 4 4 4 +1 0 3 4 2 +0 1 2 4 3 +*/ diff --git a/eBook/examples/chapter_16/pointer_interface.go b/eBook/examples/chapter_16/pointer_interface.go new file mode 100644 index 0000000..18858b4 --- /dev/null +++ b/eBook/examples/chapter_16/pointer_interface.go @@ -0,0 +1,31 @@ +// nexter.go +package main + +import ( + "fmt" +) + +type nexter interface { + next() byte +} + + +func nextFew1(n nexter, num int) []byte { + var b []byte + for i:=0; i < num; i++ { + b[i] = n.next() + } + return b +} + +func nextFew2(n *nexter, num int) []byte { + var b []byte + for i:=0; i < num; i++ { + b[i] = n.next() // compile error: n.next undefined (type *nexter has no field or method next) + } + return b +} + +func main() { + fmt.Println("Hello World!") +} diff --git a/eBook/examples/chapter_19/goto_v1/Makefile b/eBook/examples/chapter_19/goto_v1/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v1/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v1/key.go b/eBook/examples/chapter_19/goto_v1/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v1/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v1/main.go b/eBook/examples/chapter_19/goto_v1/main.go new file mode 100644 index 0000000..bcac800 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v1/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "net/http" +) + +const AddForm = ` +

    +URL: + + +` +var store = NewURLStore() + +func main() { + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(":8080", nil) +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + url := store.Get(key) + if url == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + key := store.Put(url) + fmt.Fprintf(w, "http://localhost:8080/%s", key) +} diff --git a/eBook/examples/chapter_19/goto_v1/store.go b/eBook/examples/chapter_19/goto_v1/store.go new file mode 100644 index 0000000..1d6e598 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v1/store.go @@ -0,0 +1,45 @@ +package main + +import "sync" + +type URLStore struct { + urls map[string]string + mu sync.RWMutex +} + +func NewURLStore() *URLStore { + return &URLStore{urls: make(map[string]string)} +} + +func (s *URLStore) Get(key string) string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.urls[key] +} + +func (s *URLStore) Set(key, url string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[key]; present { + return false + } + s.urls[key] = url + return true +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url string) string { + for { + key := genKey(s.Count()) // generate the short URL + if ok := s.Set(key, url); ok { + return key + } + } + // shouldn't get here + return "" +} diff --git a/eBook/examples/chapter_19/goto_v2/Makefile b/eBook/examples/chapter_19/goto_v2/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v2/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v2/key.go b/eBook/examples/chapter_19/goto_v2/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v2/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v2/main.go b/eBook/examples/chapter_19/goto_v2/main.go new file mode 100644 index 0000000..4849910 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v2/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + "net/http" +) + +var store = NewURLStore("store.gob") + +func main() { + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(":8080", nil) +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + url := store.Get(key) + if url == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + key := store.Put(url) + fmt.Fprintf(w, "http://localhost:8080/%s", key) +} + +const AddForm = ` +
    +URL: + +
    +` diff --git a/eBook/examples/chapter_19/goto_v2/store.go b/eBook/examples/chapter_19/goto_v2/store.go new file mode 100644 index 0000000..0de2fd1 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v2/store.go @@ -0,0 +1,90 @@ +package main + +import ( + "encoding/gob" + "io" + "log" + "os" + "sync" +) + +type URLStore struct { + urls map[string]string + mu sync.RWMutex + file *os.File +} + +type record struct { + Key, URL string +} + +func NewURLStore(filename string) *URLStore { + s := &URLStore{urls: make(map[string]string)} + f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal("Error opening URLStore:", err) + } + s.file = f + if err := s.load(); err != nil { + log.Println("Error loading URLStore:", err) + } + return s +} + +func (s *URLStore) Get(key string) string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.urls[key] +} + +func (s *URLStore) Set(key, url string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[key]; present { + return false + } + s.urls[key] = url + return true +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url string) string { + for { + key := genKey(s.Count()) + if ok := s.Set(key, url); ok { + if err := s.save(key, url); err != nil { + log.Println("Error saving to URLStore:", err) + } + return key + } + } + panic("shouldn't get here") +} + +func (s *URLStore) load() error { + if _, err := s.file.Seek(0, 0); err != nil { + return err + } + d := gob.NewDecoder(s.file) + var err error + for err == nil { + var r record + if err = d.Decode(&r); err == nil { + s.Set(r.Key, r.URL) + } + } + if err == io.EOF { + return nil + } + return err +} + +func (s *URLStore) save(key, url string) error { + e := gob.NewEncoder(s.file) + return e.Encode(record{key, url}) +} diff --git a/eBook/examples/chapter_19/goto_v2/store.gob b/eBook/examples/chapter_19/goto_v2/store.gob new file mode 100644 index 0000000..e69de29 diff --git a/eBook/examples/chapter_19/goto_v3/Makefile b/eBook/examples/chapter_19/goto_v3/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v3/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v3/key.go b/eBook/examples/chapter_19/goto_v3/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v3/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v3/main.go b/eBook/examples/chapter_19/goto_v3/main.go new file mode 100644 index 0000000..f7b6503 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v3/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "flag" + "fmt" + "net/http" +) + +var ( + listenAddr = flag.String("http", ":8080", "http listen address") + dataFile = flag.String("file", "store.gob", "data store file name") + hostname = flag.String("host", "localhost:8080", "http host name") +) + +var store *URLStore + +func main() { + flag.Parse() + store = NewURLStore(*dataFile) + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(*listenAddr, nil) +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + url := store.Get(key) + if url == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + key := store.Put(url) + fmt.Fprintf(w, "http://%s/%s", *hostname, key) +} + +const AddForm = ` +
    +URL: + +
    +` diff --git a/eBook/examples/chapter_19/goto_v3/store.go b/eBook/examples/chapter_19/goto_v3/store.go new file mode 100644 index 0000000..bb55289 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v3/store.go @@ -0,0 +1,111 @@ +package main + +import ( +// "bufio" + "encoding/gob" + "io" + "log" + "os" + "sync" +) + +const saveQueueLength = 1000 + +type URLStore struct { + urls map[string]string + mu sync.RWMutex + save chan record +} + +type record struct { + Key, URL string +} + +func NewURLStore(filename string) *URLStore { + s := &URLStore{ + urls: make(map[string]string), + save: make(chan record, saveQueueLength), + } + if err := s.load(filename); err != nil { + log.Println("Error loading URLStore:", err) + } + go s.saveLoop(filename) + return s +} + +func (s *URLStore) Get(key string) string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.urls[key] +} + +func (s *URLStore) Set(key, url string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[key]; present { + return false + } + s.urls[key] = url + return true +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url string) string { + for { + key := genKey(s.Count()) + if ok := s.Set(key, url); ok { + s.save <- record{key, url} + return key + } + } + panic("shouldn't get here") +} + +func (s *URLStore) load(filename string) error { + f, err := os.Open(filename) + if err != nil { + log.Println("Error opening URLStore:", err) + return err + } + defer f.Close() + // buffered reading: + // b := bufio.NewReader(f) + // d := gob.NewDecoder(b) + d := gob.NewDecoder(f) + for err == nil { + var r record + if err = d.Decode(&r); err == nil { + s.Set(r.Key, r.URL) + } + } + if err == io.EOF { + return nil + } + // error occurred: + log.Println("Error decoding URLStore:", err) // map hasn't been read correctly + return err +} + +func (s *URLStore) saveLoop(filename string) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal("Error opening URLStore: ", err) + } + defer f.Close() + e := gob.NewEncoder(f) + // buffered encoding: + // b := bufio.NewWriter(f) + // e := gob.NewEncoder(b) + // defer b.Flush() + for { + r := <-s.save // takes a record from the channel + if err := e.Encode(r); err != nil { + log.Println("Error saving to URLStore: ", err) + } + } +} diff --git a/eBook/examples/chapter_19/goto_v3/store.gob b/eBook/examples/chapter_19/goto_v3/store.gob new file mode 100644 index 0000000000000000000000000000000000000000..ded3e3d6f08b4467ee48425f62c381fba72a403d GIT binary patch literal 155 zcmY%S-^k3!$X1k^oL`i}_`ivPk%^JnJGGLLhk=nfG{^@?GcaiXZ(?LLU{ua1DJihh z*H6#SNz6;v%P&gTFUU^UPby8z%-2^AFUl-QEn-k1#y}O2frgASPy@3P^Yrpk%X1Tp Qk~8%35_405R_HST0JxJXy8r+H literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_19/goto_v4/Makefile b/eBook/examples/chapter_19/goto_v4/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v4/key.go b/eBook/examples/chapter_19/goto_v4/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v4/main.go b/eBook/examples/chapter_19/goto_v4/main.go new file mode 100644 index 0000000..3c6ee0e --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "flag" + "fmt" + "net/http" +) + +var ( + listenAddr = flag.String("http", ":8080", "http listen address") + dataFile = flag.String("file", "store.json", "data store file name") + hostname = flag.String("host", "localhost:8080", "http host name") +) + +var store *URLStore + +func main() { + flag.Parse() + store = NewURLStore(*dataFile) + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(*listenAddr, nil) +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + url := store.Get(key) + if url == "" { + http.NotFound(w, r) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + key := store.Put(url) + fmt.Fprintf(w, "http://%s/%s", *hostname, key) +} + +const AddForm = ` +
    +URL: + +
    +` diff --git a/eBook/examples/chapter_19/goto_v4/store.go b/eBook/examples/chapter_19/goto_v4/store.go new file mode 100644 index 0000000..54d5421 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/store.go @@ -0,0 +1,103 @@ +package main + +import ( + "encoding/json" + "io" + "log" + "os" + "sync" +) + +const saveQueueLength = 1000 + +type URLStore struct { + urls map[string]string + mu sync.RWMutex + save chan record +} + +type record struct { + Key, URL string +} + +func NewURLStore(filename string) *URLStore { + s := &URLStore{ + urls: make(map[string]string), + save: make(chan record, saveQueueLength), + } + if err := s.load(filename); err != nil { + log.Println("Error loading URLStore:", err) + } + go s.saveLoop(filename) + return s +} + +func (s *URLStore) Get(key string) string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.urls[key] +} + +func (s *URLStore) Set(key, url string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[key]; present { + return false + } + s.urls[key] = url + return true +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url string) string { + for { + key := genKey(s.Count()) + if ok := s.Set(key, url); ok { + s.save <- record{key, url} + return key + } + } + panic("shouldn't get here") +} + +func (s *URLStore) load(filename string) error { + f, err := os.Open(filename) + if err != nil { + log.Println("Error opening URLStore:", err) + return err + } + defer f.Close() + d := json.NewDecoder(f) + for err == nil { + var r record + if err = d.Decode(&r); err == nil { + s.Set(r.Key, r.URL) + } + } + if err == io.EOF { + return nil + } + // error occurred: + log.Println("Error decoding URLStore:", err) // map hasn't been read correctly + return err +} + +func (s *URLStore) saveLoop(filename string) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal("Error opening URLStore: ", err) + } + defer f.Close() + e := json.NewEncoder(f) + for { + r := <-s.save // takes a record from the channel + if err := e.Encode(r); err != nil { + log.Println("Error saving to URLStore: ", err) + } + } +} diff --git a/eBook/examples/chapter_19/goto_v4/store.json b/eBook/examples/chapter_19/goto_v4/store.json new file mode 100644 index 0000000..deaa85c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v4/store.json @@ -0,0 +1,4 @@ +{"Key":"0","URL":"http://www.standaard.be"} +{"Key":"1","URL":"http://www.google.be"} +{"Key":"2","URL":"http://www.gva.be"} +{"Key":"3","URL":"http://www.golang.org"} diff --git a/eBook/examples/chapter_19/goto_v5/Makefile b/eBook/examples/chapter_19/goto_v5/Makefile new file mode 100644 index 0000000..28c657c --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/Makefile @@ -0,0 +1,13 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=goto +GOFILES=\ + key.go\ + main.go\ + store.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_19/goto_v5/demo.sh b/eBook/examples/chapter_19/goto_v5/demo.sh new file mode 100644 index 0000000..e87576b --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/demo.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +gomake +./goto -http=:8081 -rpc=true & +master_pid=$! +sleep 1 +./goto -master=127.0.0.1:8081 & +slave_pid=$! +echo "Running master on :8081, slave on :8080." +echo "Visit: http://localhost:8080/add" +echo "Press enter to shut down" +read +kill $master_pid +kill $slave_pid + diff --git a/eBook/examples/chapter_19/goto_v5/key.go b/eBook/examples/chapter_19/goto_v5/key.go new file mode 100644 index 0000000..0023594 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/key.go @@ -0,0 +1,19 @@ +package main + +var keyChar = []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func genKey(n int) string { + if n == 0 { + return string(keyChar[0]) + } + l := len(keyChar) + s := make([]byte, 20) // FIXME: will overflow. eventually. + i := len(s) + for n > 0 && i >= 0 { + i-- + j := n % l + n = (n - j) / l + s[i] = keyChar[j] + } + return string(s[i:]) +} diff --git a/eBook/examples/chapter_19/goto_v5/main.go b/eBook/examples/chapter_19/goto_v5/main.go new file mode 100644 index 0000000..c054498 --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/main.go @@ -0,0 +1,70 @@ +package main + +import ( + "flag" + "fmt" + "net/http" + "net/rpc" +) + +var ( + listenAddr = flag.String("http", ":8080", "http listen address") + dataFile = flag.String("file", "store.gob", "data store file name") + hostname = flag.String("host", "localhost:8080", "http host name") + masterAddr = flag.String("master", "", "RPC master address") + rpcEnabled = flag.Bool("rpc", false, "enable RPC server") +) + +var store Store + +func main() { + flag.Parse() + if *masterAddr != "" { + store = NewProxyStore(*masterAddr) + } else { + store = NewURLStore(*dataFile) + } + if *rpcEnabled { // the master is the rpc server: + rpc.RegisterName("Store", store) + rpc.HandleHTTP() + } + http.HandleFunc("/", Redirect) + http.HandleFunc("/add", Add) + http.ListenAndServe(*listenAddr, nil) + +} + +func Redirect(w http.ResponseWriter, r *http.Request) { + key := r.URL.Path[1:] + if key == "" { + http.NotFound(w, r) + return + } + var url string + if err := store.Get(&key, &url); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, url, http.StatusFound) +} + +func Add(w http.ResponseWriter, r *http.Request) { + url := r.FormValue("url") + if url == "" { + fmt.Fprint(w, AddForm) + return + } + var key string + if err := store.Put(&url, &key); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + fmt.Fprintf(w, "http://%s/%s", *hostname, key) +} + +const AddForm = ` +
    +URL: + +
    +` diff --git a/eBook/examples/chapter_19/goto_v5/store.go b/eBook/examples/chapter_19/goto_v5/store.go new file mode 100644 index 0000000..557799f --- /dev/null +++ b/eBook/examples/chapter_19/goto_v5/store.go @@ -0,0 +1,147 @@ +package main + +import ( + "encoding/gob" + "errors" + "io" + "log" + "os" + "net/rpc" + "sync" +) + +const saveQueueLength = 1000 + +type Store interface { + Put(url, key *string) error + Get(key, url *string) error +} + +type ProxyStore struct { + urls *URLStore // local cache + client *rpc.Client +} + +type URLStore struct { + urls map[string]string + mu sync.RWMutex + save chan record +} + +type record struct { + Key, URL string +} + +func NewURLStore(filename string) *URLStore { + s := &URLStore{urls: make(map[string]string)} + if filename != "" { + s.save = make(chan record, saveQueueLength) + if err := s.load(filename); err != nil { + log.Println("Error loading URLStore: ", err) + } + go s.saveLoop(filename) + } + return s +} + +func (s *URLStore) Get(key, url *string) error { + s.mu.RLock() + defer s.mu.RUnlock() + if u, ok := s.urls[*key]; ok { + *url = u + return nil + } + return errors.New("key not found") +} + +func (s *URLStore) Set(key, url *string) error { + s.mu.Lock() + defer s.mu.Unlock() + if _, present := s.urls[*key]; present { + return errors.New("key already exists") + } + s.urls[*key] = *url + return nil +} + +func (s *URLStore) Count() int { + s.mu.RLock() + defer s.mu.RUnlock() + return len(s.urls) +} + +func (s *URLStore) Put(url, key *string) error { + for { + *key = genKey(s.Count()) + if err := s.Set(key, url); err == nil { + break + } + } + if s.save != nil { + s.save <- record{*key, *url} + } + return nil +} + +func (s *URLStore) load(filename string) error { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + d := gob.NewDecoder(f) + for err == nil { + var r record + if err = d.Decode(&r); err == nil { + s.Set(&r.Key, &r.URL) + } + } + if err == io.EOF { + return nil + } + return err +} + +func (s *URLStore) saveLoop(filename string) { + f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal("Error opening URLStore: ", err) + } + e := gob.NewEncoder(f) + for { + r := <-s.save + if err := e.Encode(r); err != nil { + log.Println("Error saving to URLStore: ", err) + } + } +} + +func NewProxyStore(addr string) *ProxyStore { + client, err := rpc.DialHTTP("tcp", addr) + if err != nil { + log.Println("Error constructing ProxyStore: ", err) + // return // ? + } + return &ProxyStore{urls: NewURLStore(""), client: client} +} + +func (s *ProxyStore) Get(key, url *string) error { + if err := s.urls.Get(key, url); err == nil { + return nil + } + // rpc call to master: + if err := s.client.Call("Store.Get", key, url); err != nil { + return err + } + s.urls.Set(key, url) // update local cache + return nil +} + +func (s *ProxyStore) Put(url, key *string) error { + // rpc call to master: + if err := s.client.Call("Store.Put", url, key); err != nil { + return err + } + s.urls.Set(key, url) // update local cache + return nil +} diff --git a/eBook/examples/chapter_19/goto_v5/store.gob b/eBook/examples/chapter_19/goto_v5/store.gob new file mode 100644 index 0000000000000000000000000000000000000000..89eabaf9600f2c5ae8c79124f087d77d3e4ff422 GIT binary patch literal 375 zcma)&F$=;l5QTFVoLmG!6hY8#LZfx_FX$wQb8KT2+gv!K#o5}wU5z?aaOiZyyZ60! z=a+X6ph+@9ilNLIG{9TR8?+dBoAv5785@>4z!bU%Yt4f5EX#tk6*?Az;$SCP&*?L0 zS9En1PVwvD2hJWsr)o!3iL6a{7Yu(2nkYrGXPG$2$R*67UrC6rD74Ka8L2-xkLn|e szmJ%dg=;$gaug;)s{l!Hb5eYF*&mUQw{*0U*ud@1f3DgiMVPv@Cz#f1RsaA1 literal 0 HcmV?d00001 diff --git a/eBook/examples/chapter_2/hello_world1.go b/eBook/examples/chapter_2/hello_world1.go index 6a6e5a7..0c71f1b 100644 --- a/eBook/examples/chapter_2/hello_world1.go +++ b/eBook/examples/chapter_2/hello_world1.go @@ -1,7 +1,7 @@ -// hello_world1.go -package main - -func main() { - println("Hello", "world") -} - +// hello_world1.go +package main + +func main() { + println("Hello", "world") +} + diff --git a/eBook/examples/chapter_2/version.go b/eBook/examples/chapter_2/version.go index 485eec4..b470bbf 100644 --- a/eBook/examples/chapter_2/version.go +++ b/eBook/examples/chapter_2/version.go @@ -1,12 +1,12 @@ -package main - -import ( - "fmt" - "runtime" -) - -func main() { - fmt.Printf("%s", runtime.Version()) -} -// Output: -// go1.0.3 or go 1.1 +package main + +import ( + "fmt" + "runtime" +) + +func main() { + fmt.Printf("%s", runtime.Version()) +} +// Output: +// go1.0.3 or go 1.1 diff --git a/eBook/examples/chapter_20/helloapp/app.yaml b/eBook/examples/chapter_20/helloapp/app.yaml new file mode 100644 index 0000000..baa19d9 --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/app.yaml @@ -0,0 +1,8 @@ +application: helloworld +version: 1 +runtime: go +api_version: 3 + +handlers: +- url: /.* + script: _go_app diff --git a/eBook/examples/chapter_20/helloapp/hello/helloworld2_version1.go b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version1.go new file mode 100644 index 0000000..66d664d --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version1.go @@ -0,0 +1,14 @@ +package hello + +import ( + "fmt" + "net/http" +) + +func init() { + http.HandleFunc("/", handler) +} + +func handler(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Hello, world!") +} diff --git a/eBook/examples/chapter_20/helloapp/hello/helloworld2_version2.go b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version2.go new file mode 100644 index 0000000..848a534 --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version2.go @@ -0,0 +1,28 @@ +package hello + +import ( + "appengine" + "appengine/user" + "fmt" + "net/http" +) + +func init() { + http.HandleFunc("/", handler) +} + +func handler(w http.ResponseWriter, r *http.Request) { + c := appengine.NewContext(r) + u := user.Current(c) + if u == nil { + url, err := user.LoginURL(c, r.URL.String()) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + w.Header().Set("Location", url) + w.WriteHeader(http.StatusFound) + return + } + fmt.Fprintf(w, "Hello, %v!", u) +} diff --git a/eBook/examples/chapter_20/helloapp/hello/helloworld2_version3.go b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version3.go new file mode 100644 index 0000000..38a5f50 --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version3.go @@ -0,0 +1,46 @@ +package hello + +import ( + "fmt" + "net/http" + "template" +) + +const guestbookForm = ` + + +
    +
    +
    +
    + + +` +const signTemplateHTML = ` + + +

    You wrote:

    +
    {{html .}}
    + + +` +var signTemplate = template.Must(template.New("sign").Parse(signTemplateHTML)) + +func init() { + http.HandleFunc("/", root) + http.HandleFunc("/sign", sign) +} + +func root(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html") + fmt.Fprint(w, guestbookForm) +} + +func sign(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html") + err := signTemplate.Execute(w, r.FormValue("content")) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + } +} + diff --git a/eBook/examples/chapter_20/helloapp/hello/helloworld2_version4.go b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version4.go new file mode 100644 index 0000000..51b72ae --- /dev/null +++ b/eBook/examples/chapter_20/helloapp/hello/helloworld2_version4.go @@ -0,0 +1,72 @@ +package hello + +import ( + "appengine" + "appengine/datastore" + "appengine/user" + "net/http" + "template" + "time" +) + +const guestbookTemplateHTML = ` + + + {{range .}} + {{with .Author}} +

    {{html .}} wrote:

    + {{else}} +

    An anonymous person wrote:

    + {{end}} +
    {{html .Content}}
    +
    {{html .Date}}
    + {{end}} +
    +
    +
    +
    + + +` +var guestbookTemplate = template.Must(template.New("book").Parse(guestbookTemplateHTML)) + +type Greeting struct { + Author string + Content string + Date datastore.Time +} + +func init() { + http.HandleFunc("/", root) + http.HandleFunc("/sign", sign) +} + +func root(w http.ResponseWriter, r *http.Request) { + c := appengine.NewContext(r) + q := datastore.NewQuery("Greeting").Order("-Date").Limit(10) + greetings := make([]Greeting, 0, 10) + if _, err := q.GetAll(c, &greetings); err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + if err := guestbookTemplate.Execute(w, greetings); err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + } +} + +func sign(w http.ResponseWriter, r *http.Request) { + c := appengine.NewContext(r) + g := Greeting{ + Content: r.FormValue("content"), + Date: datastore.SecondsToTime(time.Seconds()), + } + if u := user.Current(c); u != nil { + g.Author = u.String() + } + _, err := datastore.Put(c, datastore.NewIncompleteKey(c, "Greeting", nil), &g) + if err != nil { + http.Error(w, err.String(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, "/", http.StatusFound) +} diff --git a/eBook/examples/chapter_20/helloworld.go b/eBook/examples/chapter_20/helloworld.go new file mode 100644 index 0000000..70fa14d --- /dev/null +++ b/eBook/examples/chapter_20/helloworld.go @@ -0,0 +1,16 @@ +// helloworld.go +package helloworld + +import ( + "fmt" + "net/http" +) + +func init() { + http.HandleFunc("/", handle) +} + +func handle(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Hello, World! 세상아 안녕!! ") +} + diff --git a/eBook/examples/chapter_3/CandGo/Makefile b/eBook/examples/chapter_3/CandGo/Makefile index a05adee..9c5f632 100644 --- a/eBook/examples/chapter_3/CandGo/Makefile +++ b/eBook/examples/chapter_3/CandGo/Makefile @@ -1,7 +1,7 @@ -include $(GOROOT)/src/Make.inc - -TARG=rand -CGOFILES=\ - c1.go\ - +include $(GOROOT)/src/Make.inc + +TARG=rand +CGOFILES=\ + c1.go\ + include $(GOROOT)/src/Make.pkg \ No newline at end of file diff --git a/eBook/examples/chapter_3/CandGo/c1.go b/eBook/examples/chapter_3/CandGo/c1.go index c072630..77f1854 100644 --- a/eBook/examples/chapter_3/CandGo/c1.go +++ b/eBook/examples/chapter_3/CandGo/c1.go @@ -1,13 +1,13 @@ -// c1.go -package rand - -// #include -import "C" - -func Random() int { - return int(C.random()) -} - -func Seed(i int) { - C.srandom(C.uint(i)) -} +// c1.go +package rand + +// #include +import "C" + +func Random() int { + return int(C.random()) +} + +func Seed(i int) { + C.srandom(C.uint(i)) +} diff --git a/eBook/examples/chapter_3/CandGo/c2.go b/eBook/examples/chapter_3/CandGo/c2.go index f734763..ba96ee4 100644 --- a/eBook/examples/chapter_3/CandGo/c2.go +++ b/eBook/examples/chapter_3/CandGo/c2.go @@ -1,13 +1,13 @@ -// c2.go -package print - -// #include -// #include -import "C" -import "unsafe" - -func Print(s string) { - cs := C.CString(s) - defer C.free(unsafe.Pointer(cs)) - C.fputs(cs, (*C.FILE)(C.stdout)) -} +// c2.go +package print + +// #include +// #include +import "C" +import "unsafe" + +func Print(s string) { + cs := C.CString(s) + defer C.free(unsafe.Pointer(cs)) + C.fputs(cs, (*C.FILE)(C.stdout)) +} diff --git a/eBook/examples/chapter_3/Makefile b/eBook/examples/chapter_3/Makefile index 0026f79..0b7b04b 100644 --- a/eBook/examples/chapter_3/Makefile +++ b/eBook/examples/chapter_3/Makefile @@ -1,7 +1,7 @@ - include $(GOROOT)/src/Make.inc -TARG=test -GOFILES=\ - test1.go\ -test2.go\ - -include $(GOROOT)/src/Make.cmd + include $(GOROOT)/src/Make.inc +TARG=test +GOFILES=\ + test1.go\ +test2.go\ + +include $(GOROOT)/src/Make.cmd diff --git a/eBook/examples/chapter_3/gocomp b/eBook/examples/chapter_3/gocomp index a7c79f7..3ff0197 100644 --- a/eBook/examples/chapter_3/gocomp +++ b/eBook/examples/chapter_3/gocomp @@ -1,9 +1,9 @@ -#!/bin/bash -FILES=~/goprograms/compiletest/*.go -for f in $FILES -do - echo "Processing $f file..." - # take action on each file. $f stores current file name - # cat $f - 6g $f >> compout -done +#!/bin/bash +FILES=~/goprograms/compiletest/*.go +for f in $FILES +do + echo "Processing $f file..." + # take action on each file. $f stores current file name + # cat $f + 6g $f >> compout +done diff --git a/eBook/examples/chapter_3/gocomp.bat b/eBook/examples/chapter_3/gocomp.bat index 4c9770c..20382c1 100644 --- a/eBook/examples/chapter_3/gocomp.bat +++ b/eBook/examples/chapter_3/gocomp.bat @@ -1,2 +1,2 @@ -FOR %%X in (*.go) DO 8g %%X >> compout - +FOR %%X in (*.go) DO 8g %%X >> compout + diff --git a/eBook/examples/chapter_3/run.cmd b/eBook/examples/chapter_3/run.cmd index 9b47375..59a1d5e 100644 --- a/eBook/examples/chapter_3/run.cmd +++ b/eBook/examples/chapter_3/run.cmd @@ -1,9 +1,9 @@ -set GOROOT=E:\Go\GoforWindows\gowin32_release.r59\go -set GOBIN=$GOROOT\bin -set PATH=%PATH%;$GOBIN -set GOARCH=386 -set GOOS=windows -echo off -8g %1.go -8l -o %1.exe %1.8 -%1 +set GOROOT=E:\Go\GoforWindows\gowin32_release.r59\go +set GOBIN=$GOROOT\bin +set PATH=%PATH%;$GOBIN +set GOARCH=386 +set GOOS=windows +echo off +8g %1.go +8l -o %1.exe %1.8 +%1 diff --git a/eBook/examples/chapter_4/alias.go b/eBook/examples/chapter_4/alias.go index ba30f40..5c0c829 100644 --- a/eBook/examples/chapter_4/alias.go +++ b/eBook/examples/chapter_4/alias.go @@ -1,7 +1,7 @@ -package main - -import fm "fmt" // alias - -func main() { - fm.Println("hello, world") -} +package main + +import fm "fmt" // alias + +func main() { + fm.Println("hello, world") +} diff --git a/eBook/examples/chapter_4/casting.go b/eBook/examples/chapter_4/casting.go index 35850d6..cacf560 100644 --- a/eBook/examples/chapter_4/casting.go +++ b/eBook/examples/chapter_4/casting.go @@ -1,18 +1,18 @@ -package main -import "fmt" - -func main() { - var n int16 = 34 - var m int32 - -// compiler error: cannot use n (type int16) as type int32 in assignment - //m = n - m = int32(n) - - fmt.Printf("32 bit int is: %d\n", m) - fmt.Printf("16 bit int is: %d\n", n) -} -/* Output: -32 bit int is: 34 -16 bit int is: 34 +package main +import "fmt" + +func main() { + var n int16 = 34 + var m int32 + +// compiler error: cannot use n (type int16) as type int32 in assignment + //m = n + m = int32(n) + + fmt.Printf("32 bit int is: %d\n", m) + fmt.Printf("16 bit int is: %d\n", n) +} +/* Output: +32 bit int is: 34 +16 bit int is: 34 */ \ No newline at end of file diff --git a/eBook/examples/chapter_4/char.go b/eBook/examples/chapter_4/char.go index 67e5668..e450ab4 100644 --- a/eBook/examples/chapter_4/char.go +++ b/eBook/examples/chapter_4/char.go @@ -1,22 +1,22 @@ -// char.go -package main - -import ( - "fmt" -) - -func main() { - var ch int = '\u0041' - var ch2 int = '\u03B2' - var ch3 int = '\U00101234' - fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) - fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) - fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) - fmt.Printf("%U - %U - %U", ch, ch2, ch3) -} -/* Ouput: -65 - 946 - 1053236 -A - β - 􁈴 -41 - 3B2 - 101234 -U+0041 - U+03B2 - U+101234 +// char.go +package main + +import ( + "fmt" +) + +func main() { + var ch int = '\u0041' + var ch2 int = '\u03B2' + var ch3 int = '\U00101234' + fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) + fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) + fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) + fmt.Printf("%U - %U - %U", ch, ch2, ch3) +} +/* Ouput: +65 - 946 - 1053236 +A - β - 􁈴 +41 - 3B2 - 101234 +U+0041 - U+03B2 - U+101234 */ \ No newline at end of file diff --git a/eBook/examples/chapter_4/count_substring.go b/eBook/examples/chapter_4/count_substring.go index e97712f..d9927a6 100644 --- a/eBook/examples/chapter_4/count_substring.go +++ b/eBook/examples/chapter_4/count_substring.go @@ -1,17 +1,17 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var str string = "Hello, how is it going, Hugo?" - var manyG = "gggggggggg" - - fmt.Printf("Number of H's in %s is: ", str) - fmt.Printf("%d\n", strings.Count(str, "H")) - - fmt.Printf("Number of double g's in %s is: ", manyG) - fmt.Printf("%d\n", strings.Count(manyG, "gg")) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var str string = "Hello, how is it going, Hugo?" + var manyG = "gggggggggg" + + fmt.Printf("Number of H's in %s is: ", str) + fmt.Printf("%d\n", strings.Count(str, "H")) + + fmt.Printf("Number of double g's in %s is: ", manyG) + fmt.Printf("%d\n", strings.Count(manyG, "gg")) +} diff --git a/eBook/examples/chapter_4/function_calls_function.go b/eBook/examples/chapter_4/function_calls_function.go index 12ebdab..84509c9 100644 --- a/eBook/examples/chapter_4/function_calls_function.go +++ b/eBook/examples/chapter_4/function_calls_function.go @@ -1,15 +1,15 @@ -package main -var a string -func main() { - a = "G" - print(a) - f1() -} -func f1() { - a := "O" - print(a) - f2() -} -func f2() { - print(a) +package main +var a string +func main() { + a = "G" + print(a) + f1() +} +func f1() { + a := "O" + print(a) + f2() +} +func f2() { + print(a) } \ No newline at end of file diff --git a/eBook/examples/chapter_4/global_scope.go b/eBook/examples/chapter_4/global_scope.go index 5b1ff29..558afce 100644 --- a/eBook/examples/chapter_4/global_scope.go +++ b/eBook/examples/chapter_4/global_scope.go @@ -1,14 +1,14 @@ -package main -var a = "G" -func main() { - n() - m() - n() -} -func n() { - print(a) -} -func m() { - a = "O" - print(a) +package main +var a = "G" +func main() { + n() + m() + n() +} +func n() { + print(a) +} +func m() { + a = "O" + print(a) } \ No newline at end of file diff --git a/eBook/examples/chapter_4/goos.go b/eBook/examples/chapter_4/goos.go index 90fb6eb..9fe9a46 100644 --- a/eBook/examples/chapter_4/goos.go +++ b/eBook/examples/chapter_4/goos.go @@ -1,25 +1,25 @@ -package main -<<<<<<< HEAD - -======= ->>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 -import ( - "fmt" - "os" -) -<<<<<<< HEAD - -func main() { - var goos string = os.Getenv("GOOS") - fmt.Printf("The operating system is: %s\n", goos) - path := os.Getenv("PATH") - fmt.Printf("Path is %s\n", path) -} -======= -func main() { - var goos string = os.Getenv("GOOS") - fmt.Printf("The operating system is: %s\n", goos) - path := os.Getenv("PATH") - fmt.Printf("Path is %s\n", path) -} ->>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 +package main +<<<<<<< HEAD + +======= +>>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 +import ( + "fmt" + "os" +) +<<<<<<< HEAD + +func main() { + var goos string = os.Getenv("GOOS") + fmt.Printf("The operating system is: %s\n", goos) + path := os.Getenv("PATH") + fmt.Printf("Path is %s\n", path) +} +======= +func main() { + var goos string = os.Getenv("GOOS") + fmt.Printf("The operating system is: %s\n", goos) + path := os.Getenv("PATH") + fmt.Printf("Path is %s\n", path) +} +>>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 diff --git a/eBook/examples/chapter_4/gotemplate.go b/eBook/examples/chapter_4/gotemplate.go index 68de9ca..aafb5ab 100644 --- a/eBook/examples/chapter_4/gotemplate.go +++ b/eBook/examples/chapter_4/gotemplate.go @@ -1,30 +1,30 @@ -package main - -import ( - "fmt" -) - -const c = "C" - -var v int = 5 - -type T struct{} - -func init() { - // initialization of package -} - -func main() { - var a int - Func1() - // ... - fmt.Println(a) -} - -func (t T) Method1() { - //... -} - -func Func1() { // exported function Func1 - //... -} +package main + +import ( + "fmt" +) + +const c = "C" + +var v int = 5 + +type T struct{} + +func init() { + // initialization of package +} + +func main() { + var a int + Func1() + // ... + fmt.Println(a) +} + +func (t T) Method1() { + //... +} + +func Func1() { // exported function Func1 + //... +} diff --git a/eBook/examples/chapter_4/hello_world.go b/eBook/examples/chapter_4/hello_world.go index c3cb0ae..8e4e589 100644 --- a/eBook/examples/chapter_4/hello_world.go +++ b/eBook/examples/chapter_4/hello_world.go @@ -1,7 +1,7 @@ -package main - -import "fmt" - -func main() { - fmt.Println("hello, world") -} +package main + +import "fmt" + +func main() { + fmt.Println("hello, world") +} diff --git a/eBook/examples/chapter_4/hello_world2.go b/eBook/examples/chapter_4/hello_world2.go index e8e85c4..c52d126 100644 --- a/eBook/examples/chapter_4/hello_world2.go +++ b/eBook/examples/chapter_4/hello_world2.go @@ -1,7 +1,7 @@ -package main - -import "fmt" // Package implementing formatted I/O. - -func main() { - fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n") -} +package main + +import "fmt" // Package implementing formatted I/O. + +func main() { + fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n") +} diff --git a/eBook/examples/chapter_4/index_in_string.go b/eBook/examples/chapter_4/index_in_string.go index 2964bfa..abc9d07 100644 --- a/eBook/examples/chapter_4/index_in_string.go +++ b/eBook/examples/chapter_4/index_in_string.go @@ -1,21 +1,21 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var str string = "Hi, I'm Marc, Hi." - - fmt.Printf("The position of \"Marc\" is: ") - fmt.Printf("%d\n", strings.Index(str, "Marc")) - - fmt.Printf("The position of the first instance of \"Hi\" is: ") - fmt.Printf("%d\n", strings.Index(str, "Hi")) - fmt.Printf("The position of the last instance of \"Hi\" is: ") - fmt.Printf("%d\n", strings.LastIndex(str, "Hi")) - - fmt.Printf("The position of \"Burger\" is: ") - fmt.Printf("%d\n", strings.Index(str, "Burger")) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var str string = "Hi, I'm Marc, Hi." + + fmt.Printf("The position of \"Marc\" is: ") + fmt.Printf("%d\n", strings.Index(str, "Marc")) + + fmt.Printf("The position of the first instance of \"Hi\" is: ") + fmt.Printf("%d\n", strings.Index(str, "Hi")) + fmt.Printf("The position of the last instance of \"Hi\" is: ") + fmt.Printf("%d\n", strings.LastIndex(str, "Hi")) + + fmt.Printf("The position of \"Burger\" is: ") + fmt.Printf("%d\n", strings.Index(str, "Burger")) +} diff --git a/eBook/examples/chapter_4/init.go b/eBook/examples/chapter_4/init.go index 26f07ca..023e570 100644 --- a/eBook/examples/chapter_4/init.go +++ b/eBook/examples/chapter_4/init.go @@ -1,17 +1,17 @@ -package trans -<<<<<<< HEAD - -import "math" - -var Pi float64 - -func init() { - Pi = 4 * math.Atan(1) // init() function computes Pi -} -======= -import "math" -var Pi float64 -func init() { - Pi = 4 * math.Atan(1) // init() function computes Pi -} ->>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 +package trans +<<<<<<< HEAD + +import "math" + +var Pi float64 + +func init() { + Pi = 4 * math.Atan(1) // init() function computes Pi +} +======= +import "math" +var Pi float64 +func init() { + Pi = 4 * math.Atan(1) // init() function computes Pi +} +>>>>>>> 0364d180eb1d1b8067d1248ace49ca46c816e541 diff --git a/eBook/examples/chapter_4/local_scope.go b/eBook/examples/chapter_4/local_scope.go index 7fd3aea..decff22 100644 --- a/eBook/examples/chapter_4/local_scope.go +++ b/eBook/examples/chapter_4/local_scope.go @@ -1,12 +1,12 @@ -package main -var a = "G" -func main() { - n() - m() - n() -} -func n() { print(a) } -func m() { - a := "O" - print(a) +package main +var a = "G" +func main() { + n() + m() + n() +} +func n() { print(a) } +func m() { + a := "O" + print(a) } \ No newline at end of file diff --git a/eBook/examples/chapter_4/pointer.go b/eBook/examples/chapter_4/pointer.go index ff230fd..1ae2248 100644 --- a/eBook/examples/chapter_4/pointer.go +++ b/eBook/examples/chapter_4/pointer.go @@ -1,12 +1,12 @@ -package main - -import "fmt" - -func main() { - var i1 = 5 - fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1) - - var intP *int - intP = &i1 - fmt.Printf("The value at memory location %p is %d\n", intP, *intP) -} +package main + +import "fmt" + +func main() { + var i1 = 5 + fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1) + + var intP *int + intP = &i1 + fmt.Printf("The value at memory location %p is %d\n", intP, *intP) +} diff --git a/eBook/examples/chapter_4/presuffix.go b/eBook/examples/chapter_4/presuffix.go index c7484f6..7b4fd88 100644 --- a/eBook/examples/chapter_4/presuffix.go +++ b/eBook/examples/chapter_4/presuffix.go @@ -1,14 +1,14 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var str string = "This is an example of a string" - - fmt.Printf("T/F? Does the string \"%s\" have prefix %s? ", str, "Th") - fmt.Printf("%t\n", strings.HasPrefix(str, "Th")) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var str string = "This is an example of a string" + + fmt.Printf("T/F? Does the string \"%s\" have prefix %s? ", str, "Th") + fmt.Printf("%t\n", strings.HasPrefix(str, "Th")) +} // Output: T/F? Does the string "This is an example of a string" have prefix Th? true \ No newline at end of file diff --git a/eBook/examples/chapter_4/random.go b/eBook/examples/chapter_4/random.go index 9dc8e61..2c5c604 100644 --- a/eBook/examples/chapter_4/random.go +++ b/eBook/examples/chapter_4/random.go @@ -1,28 +1,28 @@ -package main - -import ( - "fmt" - "math/rand" - "time" -) - -func main() { - for i := 0; i < 10; i++ { - a := rand.Int() - fmt.Printf("%d / ", a) - } - for i := 0; i < 5; i++ { - r := rand.Intn(8) - fmt.Printf("%d / ", r) - } - fmt.Println() - timens := int64(time.Now().Nanosecond()) - rand.Seed(timens) - for i := 0; i < 10; i++ { - fmt.Printf("%2.2f / ", 100*rand.Float32()) - } -} -/* Output: -134020434 / 1597969999 / 1721070109 / 2068675587 / 1237770961 / 220031192 / 2031484958 / 583324308 / 958990240 / 413002649 / 6 / 7 / 2 / 1 / 0 / -22.84 / 10.12 / 44.32 / 58.58 / 15.49 / 12.23 / 30.16 / 88.48 / 34.26 / 27.18 / -*/ +package main + +import ( + "fmt" + "math/rand" + "time" +) + +func main() { + for i := 0; i < 10; i++ { + a := rand.Int() + fmt.Printf("%d / ", a) + } + for i := 0; i < 5; i++ { + r := rand.Intn(8) + fmt.Printf("%d / ", r) + } + fmt.Println() + timens := int64(time.Now().Nanosecond()) + rand.Seed(timens) + for i := 0; i < 10; i++ { + fmt.Printf("%2.2f / ", 100*rand.Float32()) + } +} +/* Output: +134020434 / 1597969999 / 1721070109 / 2068675587 / 1237770961 / 220031192 / 2031484958 / 583324308 / 958990240 / 413002649 / 6 / 7 / 2 / 1 / 0 / +22.84 / 10.12 / 44.32 / 58.58 / 15.49 / 12.23 / 30.16 / 88.48 / 34.26 / 27.18 / +*/ diff --git a/eBook/examples/chapter_4/repeat_string.go b/eBook/examples/chapter_4/repeat_string.go index 043ee14..426e76f 100644 --- a/eBook/examples/chapter_4/repeat_string.go +++ b/eBook/examples/chapter_4/repeat_string.go @@ -1,14 +1,14 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var origS string = "Hi there! " - var newS string - - newS = strings.Repeat(origS, 3) - fmt.Printf("The new repeated string is: %s\n", newS) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var origS string = "Hi there! " + var newS string + + newS = strings.Repeat(origS, 3) + fmt.Printf("The new repeated string is: %s\n", newS) +} diff --git a/eBook/examples/chapter_4/string_conversion.go b/eBook/examples/chapter_4/string_conversion.go index 4506023..61a6ff1 100644 --- a/eBook/examples/chapter_4/string_conversion.go +++ b/eBook/examples/chapter_4/string_conversion.go @@ -1,20 +1,20 @@ -package main - -import ( - "fmt" - "strconv" -) - -func main() { - var orig string = "666" - var an int - var newS string - - fmt.Printf("The size of ints is: %d\n", strconv.IntSize) - - an, _ = strconv.Atoi(orig) - fmt.Printf("The integer is: %d\n", an) - an = an + 5 - newS = strconv.Itoa(an) - fmt.Printf("The new string is: %s\n", newS) -} +package main + +import ( + "fmt" + "strconv" +) + +func main() { + var orig string = "666" + var an int + var newS string + + fmt.Printf("The size of ints is: %d\n", strconv.IntSize) + + an, _ = strconv.Atoi(orig) + fmt.Printf("The integer is: %d\n", an) + an = an + 5 + newS = strconv.Itoa(an) + fmt.Printf("The new string is: %s\n", newS) +} diff --git a/eBook/examples/chapter_4/string_pointer.go b/eBook/examples/chapter_4/string_pointer.go index abd62bd..7448423 100644 --- a/eBook/examples/chapter_4/string_pointer.go +++ b/eBook/examples/chapter_4/string_pointer.go @@ -1,13 +1,13 @@ -package main - -import "fmt" - -func main() { - s := "good bye" - var p *string = &s - *p = "ciao" - - fmt.Printf("Here is the pointer p: %p\n", p) // prints address - fmt.Printf("Here is the string *p: %s\n", *p) // prints string - fmt.Printf("Here is the string s: %s\n", s) // prints same string -} +package main + +import "fmt" + +func main() { + s := "good bye" + var p *string = &s + *p = "ciao" + + fmt.Printf("Here is the pointer p: %p\n", p) // prints address + fmt.Printf("Here is the string *p: %s\n", *p) // prints string + fmt.Printf("Here is the string s: %s\n", s) // prints same string +} diff --git a/eBook/examples/chapter_4/strings_splitjoin.go b/eBook/examples/chapter_4/strings_splitjoin.go index 8d64620..a31d43c 100644 --- a/eBook/examples/chapter_4/strings_splitjoin.go +++ b/eBook/examples/chapter_4/strings_splitjoin.go @@ -1,33 +1,33 @@ -// strings.go -package main - -import ( - "fmt" - "strings" -) - -func main() { - str := "The quick brown fox jumps over the lazy dog" - sl := strings.Fields(str) - fmt.Printf("Splitted in slice: %v\n", sl) - for _, val := range sl { - fmt.Printf("%s - ", val) - } - fmt.Println() - str2 := "GO1|The ABC of Go|25" - sl2 := strings.Split(str2, "|") - fmt.Printf("Splitted in slice: %v\n", sl2) - for _, val := range sl2 { - fmt.Printf("%s - ", val) - } - fmt.Println() - str3 := strings.Join(sl2,";") - fmt.Printf("sl2 joined by ;: %s\n", str3) -} -/* Output: -Splitted in slice: [The quick brown fox jumps over the lazy dog] -The - quick - brown - fox - jumps - over - the - lazy - dog - -Splitted in slice: [GO1 The ABC of Go 25] -GO1 - The ABC of Go - 25 - -sl2 joined by ;: GO1;The ABC of Go;25 +// strings.go +package main + +import ( + "fmt" + "strings" +) + +func main() { + str := "The quick brown fox jumps over the lazy dog" + sl := strings.Fields(str) + fmt.Printf("Splitted in slice: %v\n", sl) + for _, val := range sl { + fmt.Printf("%s - ", val) + } + fmt.Println() + str2 := "GO1|The ABC of Go|25" + sl2 := strings.Split(str2, "|") + fmt.Printf("Splitted in slice: %v\n", sl2) + for _, val := range sl2 { + fmt.Printf("%s - ", val) + } + fmt.Println() + str3 := strings.Join(sl2,";") + fmt.Printf("sl2 joined by ;: %s\n", str3) +} +/* Output: +Splitted in slice: [The quick brown fox jumps over the lazy dog] +The - quick - brown - fox - jumps - over - the - lazy - dog - +Splitted in slice: [GO1 The ABC of Go 25] +GO1 - The ABC of Go - 25 - +sl2 joined by ;: GO1;The ABC of Go;25 */ \ No newline at end of file diff --git a/eBook/examples/chapter_4/testcrash.go b/eBook/examples/chapter_4/testcrash.go index e2891c1..faff80f 100644 --- a/eBook/examples/chapter_4/testcrash.go +++ b/eBook/examples/chapter_4/testcrash.go @@ -1,11 +1,11 @@ -// testcrash.go -// compiles , but crashes -package main - -func main() { - var p *int = nil - *p = 0 - -} -// in Windows: stops only with: -// runtime error: invalid memory address or nil pointer dereference +// testcrash.go +// compiles , but crashes +package main + +func main() { + var p *int = nil + *p = 0 + +} +// in Windows: stops only with: +// runtime error: invalid memory address or nil pointer dereference diff --git a/eBook/examples/chapter_4/time.go b/eBook/examples/chapter_4/time.go index 1228c20..4ebf08e 100644 --- a/eBook/examples/chapter_4/time.go +++ b/eBook/examples/chapter_4/time.go @@ -1,27 +1,27 @@ -package main - -import ( - "fmt" - "time" -) - -var week time.Duration - -func main() { - t := time.Now() - fmt.Println(t) // Wed Dec 21 09:52:14 +0100 RST 2011 - fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year()) // 21.12.2011 - t = time.Now().UTC() - fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011 - fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011 - // calculating times: - week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec - week_from_now := t.Add(week) - fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011 - // formatting times: - fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC - fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011 - fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52 - s := t.Format("20060102") - fmt.Println(t, "=>", s) // Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221 -} +package main + +import ( + "fmt" + "time" +) + +var week time.Duration + +func main() { + t := time.Now() + fmt.Println(t) // Wed Dec 21 09:52:14 +0100 RST 2011 + fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year()) // 21.12.2011 + t = time.Now().UTC() + fmt.Println(t) // Wed Dec 21 08:52:14 +0000 UTC 2011 + fmt.Println(time.Now()) // Wed Dec 21 09:52:14 +0100 RST 2011 + // calculating times: + week = 60 * 60 * 24 * 7 * 1e9 // must be in nanosec + week_from_now := t.Add(week) + fmt.Println(week_from_now) // Wed Dec 28 08:52:14 +0000 UTC 2011 + // formatting times: + fmt.Println(t.Format(time.RFC822)) // 21 Dec 11 0852 UTC + fmt.Println(t.Format(time.ANSIC)) // Wed Dec 21 08:56:34 2011 + fmt.Println(t.Format("02 Jan 2006 15:04")) // 21 Dec 2011 08:52 + s := t.Format("20060102") + fmt.Println(t, "=>", s) // Wed Dec 21 08:52:14 +0000 UTC 2011 => 20111221 +} diff --git a/eBook/examples/chapter_4/toupper_lower.go b/eBook/examples/chapter_4/toupper_lower.go index a170831..6cb2b36 100644 --- a/eBook/examples/chapter_4/toupper_lower.go +++ b/eBook/examples/chapter_4/toupper_lower.go @@ -1,18 +1,18 @@ -package main - -import ( - "fmt" - "strings" -) - -func main() { - var orig string = "Hey, how are you George?" - var lower string - var upper string - - fmt.Printf("The original string is: %s\n", orig) - lower = strings.ToLower(orig) - fmt.Printf("The lowercase string is: %s\n", lower) - upper = strings.ToUpper(orig) - fmt.Printf("The uppercase string is: %s\n", upper) -} +package main + +import ( + "fmt" + "strings" +) + +func main() { + var orig string = "Hey, how are you George?" + var lower string + var upper string + + fmt.Printf("The original string is: %s\n", orig) + lower = strings.ToLower(orig) + fmt.Printf("The lowercase string is: %s\n", lower) + upper = strings.ToUpper(orig) + fmt.Printf("The uppercase string is: %s\n", upper) +} diff --git a/eBook/examples/chapter_4/type.go b/eBook/examples/chapter_4/type.go index 5f1d539..a541098 100644 --- a/eBook/examples/chapter_4/type.go +++ b/eBook/examples/chapter_4/type.go @@ -1,11 +1,11 @@ -package main - -import "fmt" - -type TZ int - -func main() { - var a, b TZ = 3, 4 - c := a + b - fmt.Printf("c has the value: %d", c) +package main + +import "fmt" + +type TZ int + +func main() { + var a, b TZ = 3, 4 + c := a + b + fmt.Printf("c has the value: %d", c) } \ No newline at end of file diff --git a/eBook/examples/chapter_4/type_mixing.go b/eBook/examples/chapter_4/type_mixing.go index d59eee8..1814249 100644 --- a/eBook/examples/chapter_4/type_mixing.go +++ b/eBook/examples/chapter_4/type_mixing.go @@ -1,9 +1,9 @@ -package main - -func main() { - var a int - var b int32 - a = 15 - b = a + a // compiler error - b = b + 5 // ok: 5 is a constant +package main + +func main() { + var a int + var b int32 + a = 15 + b = a + a // compiler error + b = b + 5 // ok: 5 is a constant } \ No newline at end of file diff --git a/eBook/examples/chapter_4/use_init.go b/eBook/examples/chapter_4/use_init.go index 9cdf255..9b9a62f 100644 --- a/eBook/examples/chapter_4/use_init.go +++ b/eBook/examples/chapter_4/use_init.go @@ -1,12 +1,12 @@ -package main - -import ( - "fmt" - "./trans" -) - -var twoPi = 2 * trans.Pi // decl computes twoPi - -func main() { - fmt.Printf("2*Pi = %g\n", twoPi) // 2*Pi = 6.283185307179586 -} +package main + +import ( + "fmt" + "./trans" +) + +var twoPi = 2 * trans.Pi // decl computes twoPi + +func main() { + fmt.Printf("2*Pi = %g\n", twoPi) // 2*Pi = 6.283185307179586 +} diff --git a/eBook/examples/chapter_4/user_init.go b/eBook/examples/chapter_4/user_init.go index fc59361..6f4dd20 100644 --- a/eBook/examples/chapter_4/user_init.go +++ b/eBook/examples/chapter_4/user_init.go @@ -1,9 +1,9 @@ -package main -import ( - "fmt" - "./trans" -) -var twoPi = 2 * trans.Pi -func main() { - fmt.Printf("2*Pi = %g\n", twoPi) // 2*Pi = 6.283185307179586 +package main +import ( + "fmt" + "./trans" +) +var twoPi = 2 * trans.Pi +func main() { + fmt.Printf("2*Pi = %g\n", twoPi) // 2*Pi = 6.283185307179586 } \ No newline at end of file diff --git a/eBook/examples/chapter_5/booleans.go b/eBook/examples/chapter_5/booleans.go index bcf145f..3b29401 100644 --- a/eBook/examples/chapter_5/booleans.go +++ b/eBook/examples/chapter_5/booleans.go @@ -1,12 +1,12 @@ -package main - -import "fmt" - -func main() { - bool1 := true - if bool1 { - fmt.Printf("The value is true\n") - } else { - fmt.Printf("The value is false\n") - } -} +package main + +import "fmt" + +func main() { + bool1 := true + if bool1 { + fmt.Printf("The value is true\n") + } else { + fmt.Printf("The value is false\n") + } +} diff --git a/eBook/examples/chapter_5/for1.go b/eBook/examples/chapter_5/for1.go index 79f958a..66efa90 100644 --- a/eBook/examples/chapter_5/for1.go +++ b/eBook/examples/chapter_5/for1.go @@ -1,9 +1,9 @@ -package main - -import "fmt" - -func main() { - for i := 0; i < 5; i++ { - fmt.Printf("This is the %d iteration\n", i) - } -} +package main + +import "fmt" + +func main() { + for i := 0; i < 5; i++ { + fmt.Printf("This is the %d iteration\n", i) + } +} diff --git a/eBook/examples/chapter_5/for2.go b/eBook/examples/chapter_5/for2.go index bf9b294..dceb993 100644 --- a/eBook/examples/chapter_5/for2.go +++ b/eBook/examples/chapter_5/for2.go @@ -1,12 +1,12 @@ -package main - -import "fmt" - -func main() { - var i int = 5 - - for i >= 0 { - i = i - 1 - fmt.Printf("The variable i is now: %d\n", i) - } -} +package main + +import "fmt" + +func main() { + var i int = 5 + + for i >= 0 { + i = i - 1 + fmt.Printf("The variable i is now: %d\n", i) + } +} diff --git a/eBook/examples/chapter_5/for3.go b/eBook/examples/chapter_5/for3.go index 62bd74b..7a045ae 100644 --- a/eBook/examples/chapter_5/for3.go +++ b/eBook/examples/chapter_5/for3.go @@ -1,15 +1,15 @@ -package main - -import "fmt" - -func main() { - var i int = 5 - - for { - i = i - 1 - fmt.Printf("The variable i is now: %d\n", i) - if i < 0 { - break - } - } -} +package main + +import "fmt" + +func main() { + var i int = 5 + + for { + i = i - 1 + fmt.Printf("The variable i is now: %d\n", i) + if i < 0 { + break + } + } +} diff --git a/eBook/examples/chapter_5/for4.go b/eBook/examples/chapter_5/for4.go index cb16d54..6f5c7ab 100644 --- a/eBook/examples/chapter_5/for4.go +++ b/eBook/examples/chapter_5/for4.go @@ -1,13 +1,13 @@ -package main - -func main() { - for i:=0; i<3; i++ { - for j:=0; j<10; j++ { - if j>5 { - break - } - print(j) - } - print(" ") - } +package main + +func main() { + for i:=0; i<3; i++ { + for j:=0; j<10; j++ { + if j>5 { + break + } + print(j) + } + print(" ") + } } \ No newline at end of file diff --git a/eBook/examples/chapter_5/for5.go b/eBook/examples/chapter_5/for5.go index 6e1135e..475b926 100644 --- a/eBook/examples/chapter_5/for5.go +++ b/eBook/examples/chapter_5/for5.go @@ -1,11 +1,11 @@ -package main - -func main() { - for i := 0; i < 10; i++ { - if i == 5 { - continue - } - print(i) - print(" ") - } -} +package main + +func main() { + for i := 0; i < 10; i++ { + if i == 5 { + continue + } + print(i) + print(" ") + } +} diff --git a/eBook/examples/chapter_5/for6.go b/eBook/examples/chapter_5/for6.go index 81a96d8..bf04e78 100644 --- a/eBook/examples/chapter_5/for6.go +++ b/eBook/examples/chapter_5/for6.go @@ -1,17 +1,17 @@ -package main - -import "fmt" - -func main() { - -LABEL1: - for i := 0; i <= 5; i++ { - for j := 0; j <= 5; j++ { - if j == 4 { - continue LABEL1 - } - fmt.Printf("i is: %d, and j is: %d\n", i, j) - } - } - -} +package main + +import "fmt" + +func main() { + +LABEL1: + for i := 0; i <= 5; i++ { + for j := 0; j <= 5; j++ { + if j == 4 { + continue LABEL1 + } + fmt.Printf("i is: %d, and j is: %d\n", i, j) + } + } + +} diff --git a/eBook/examples/chapter_5/for_string.go b/eBook/examples/chapter_5/for_string.go index 7b18921..97b8d59 100644 --- a/eBook/examples/chapter_5/for_string.go +++ b/eBook/examples/chapter_5/for_string.go @@ -1,57 +1,57 @@ -// for_string.go -package main - -import "fmt" - -func main() { - str := "Go is a beautiful language!" - fmt.Printf("The length of str is: %d\n", len(str)) - for ix :=0; ix < len(str); ix++ { - fmt.Printf("Character on position %d is: %c \n", ix, str[ix]) - } - str2 := "日本語" - fmt.Printf("The length of str2 is: %d\n", len(str2)) - for ix :=0; ix < len(str2); ix++ { - fmt.Printf("Character on position %d is: %c \n", ix, str2[ix]) - } -} -/* Output: -The length of str is: 27 -Character on position 0 is: G -Character on position 1 is: o -Character on position 2 is: -Character on position 3 is: i -Character on position 4 is: s -Character on position 5 is: -Character on position 6 is: a -Character on position 7 is: -Character on position 8 is: b -Character on position 9 is: e -Character on position 10 is: a -Character on position 11 is: u -Character on position 12 is: t -Character on position 13 is: i -Character on position 14 is: f -Character on position 15 is: u -Character on position 16 is: l -Character on position 17 is: -Character on position 18 is: l -Character on position 19 is: a -Character on position 20 is: n -Character on position 21 is: g -Character on position 22 is: u -Character on position 23 is: a -Character on position 24 is: g -Character on position 25 is: e -Character on position 26 is: ! -The length of str2 is: 9 -Character on position 0 is: æ -Character on position 1 is: — -Character on position 2 is: ¥ -Character on position 3 is: æ -Character on position 4 is: œ -Character on position 5 is: ¬ -Character on position 6 is: è -Character on position 7 is: ª -Character on position 8 is: ž +// for_string.go +package main + +import "fmt" + +func main() { + str := "Go is a beautiful language!" + fmt.Printf("The length of str is: %d\n", len(str)) + for ix :=0; ix < len(str); ix++ { + fmt.Printf("Character on position %d is: %c \n", ix, str[ix]) + } + str2 := "日本語" + fmt.Printf("The length of str2 is: %d\n", len(str2)) + for ix :=0; ix < len(str2); ix++ { + fmt.Printf("Character on position %d is: %c \n", ix, str2[ix]) + } +} +/* Output: +The length of str is: 27 +Character on position 0 is: G +Character on position 1 is: o +Character on position 2 is: +Character on position 3 is: i +Character on position 4 is: s +Character on position 5 is: +Character on position 6 is: a +Character on position 7 is: +Character on position 8 is: b +Character on position 9 is: e +Character on position 10 is: a +Character on position 11 is: u +Character on position 12 is: t +Character on position 13 is: i +Character on position 14 is: f +Character on position 15 is: u +Character on position 16 is: l +Character on position 17 is: +Character on position 18 is: l +Character on position 19 is: a +Character on position 20 is: n +Character on position 21 is: g +Character on position 22 is: u +Character on position 23 is: a +Character on position 24 is: g +Character on position 25 is: e +Character on position 26 is: ! +The length of str2 is: 9 +Character on position 0 is: æ +Character on position 1 is: — +Character on position 2 is: ¥ +Character on position 3 is: æ +Character on position 4 is: œ +Character on position 5 is: ¬ +Character on position 6 is: è +Character on position 7 is: ª +Character on position 8 is: ž */ \ No newline at end of file diff --git a/eBook/examples/chapter_5/goto.go b/eBook/examples/chapter_5/goto.go index e61b47c..c36a7ea 100644 --- a/eBook/examples/chapter_5/goto.go +++ b/eBook/examples/chapter_5/goto.go @@ -1,12 +1,12 @@ -package main - -func main() { - i:=0 - HERE: - print(i) - i++ - if i==5 { - return - } - goto HERE +package main + +func main() { + i:=0 + HERE: + print(i) + i++ + if i==5 { + return + } + goto HERE } \ No newline at end of file diff --git a/eBook/examples/chapter_5/goto2.go b/eBook/examples/chapter_5/goto2.go index 705b9a9..118f47c 100644 --- a/eBook/examples/chapter_5/goto2.go +++ b/eBook/examples/chapter_5/goto2.go @@ -1,13 +1,13 @@ -// compile error goto2.go:8: goto TARGET jumps over declaration of b at goto2.go:8 -package main - -import "fmt" - -func main() { - a := 1 - goto TARGET // compile error - b := 9 - TARGET: - b += a - fmt.Printf("a is %v *** b is %v", a, b) +// compile error goto2.go:8: goto TARGET jumps over declaration of b at goto2.go:8 +package main + +import "fmt" + +func main() { + a := 1 + goto TARGET // compile error + b := 9 + TARGET: + b += a + fmt.Printf("a is %v *** b is %v", a, b) } \ No newline at end of file diff --git a/eBook/examples/chapter_5/ifelse.go b/eBook/examples/chapter_5/ifelse.go index 0b8dc61..aad629e 100644 --- a/eBook/examples/chapter_5/ifelse.go +++ b/eBook/examples/chapter_5/ifelse.go @@ -1,22 +1,22 @@ -package main - -import "fmt" - -func main() { - var first int = 10 - var cond int - - if first <= 0 { - fmt.Printf("first is less than or equal to 0\n") - } else if first > 0 && first < 5 { - fmt.Printf("first is between 0 and 5\n") - } else { - fmt.Printf("first is 5 or greater\n") - } - - if cond = 5; cond > 10 { - fmt.Printf("cond is greater than 10\n") - } else { - fmt.Printf("cond is not greater than 10\n") - } -} +package main + +import "fmt" + +func main() { + var first int = 10 + var cond int + + if first <= 0 { + fmt.Printf("first is less than or equal to 0\n") + } else if first > 0 && first < 5 { + fmt.Printf("first is between 0 and 5\n") + } else { + fmt.Printf("first is 5 or greater\n") + } + + if cond = 5; cond > 10 { + fmt.Printf("cond is greater than 10\n") + } else { + fmt.Printf("cond is not greater than 10\n") + } +} diff --git a/eBook/examples/chapter_5/range_string.go b/eBook/examples/chapter_5/range_string.go index f5bdc2e..465b392 100644 --- a/eBook/examples/chapter_5/range_string.go +++ b/eBook/examples/chapter_5/range_string.go @@ -1,80 +1,80 @@ -package main - -import "fmt" - -func main() { - str := "Go is a beautiful language!" - fmt.Printf("The length of str is: %d\n", len(str)) - for pos, char := range str { - fmt.Printf("Character on position %d is: %c \n", pos, char) - } - fmt.Println() - str2 := "Chinese: 日本語" - fmt.Printf("The length of str2 is: %d\n", len(str2)) - for pos, char := range str2 { - fmt.Printf("character %c starts at byte position %d\n", char, pos) - } - fmt.Println() - fmt.Println("index int(rune) rune char bytes") - for index, rune := range str2 { - fmt.Printf("%-2d %d %U '%c' % X\n", index, rune, rune, rune, []byte(string(rune))) - } -} -/* Output: -The length of str is: 27 -Character on position 0 is: G -Character on position 1 is: o -Character on position 2 is: -Character on position 3 is: i -Character on position 4 is: s -Character on position 5 is: -Character on position 6 is: a -Character on position 7 is: -Character on position 8 is: b -Character on position 9 is: e -Character on position 10 is: a -Character on position 11 is: u -Character on position 12 is: t -Character on position 13 is: i -Character on position 14 is: f -Character on position 15 is: u -Character on position 16 is: l -Character on position 17 is: -Character on position 18 is: l -Character on position 19 is: a -Character on position 20 is: n -Character on position 21 is: g -Character on position 22 is: u -Character on position 23 is: a -Character on position 24 is: g -Character on position 25 is: e -Character on position 26 is: ! - -The length of str2 is: 18 -character C starts at byte position 0 -character h starts at byte position 1 -character i starts at byte position 2 -character n starts at byte position 3 -character e starts at byte position 4 -character s starts at byte position 5 -character e starts at byte position 6 -character : starts at byte position 7 -character starts at byte position 8 -character 日 starts at byte position 9 -character 本 starts at byte position 12 -character 語 starts at byte position 15 - -index int(rune) rune char bytes -0 67 U+0043 'C' 43 -1 104 U+0068 'h' 68 -2 105 U+0069 'i' 69 -3 110 U+006E 'n' 6E -4 101 U+0065 'e' 65 -5 115 U+0073 's' 73 -6 101 U+0065 'e' 65 -7 58 U+003A ':' 3A -8 32 U+0020 ' ' 20 -9 26085 U+65E5 '日' E6 97 A5 -12 26412 U+672C '本' E6 9C AC -15 35486 U+8A9E '語' E8 AA 9E -*/ +package main + +import "fmt" + +func main() { + str := "Go is a beautiful language!" + fmt.Printf("The length of str is: %d\n", len(str)) + for pos, char := range str { + fmt.Printf("Character on position %d is: %c \n", pos, char) + } + fmt.Println() + str2 := "Chinese: 日本語" + fmt.Printf("The length of str2 is: %d\n", len(str2)) + for pos, char := range str2 { + fmt.Printf("character %c starts at byte position %d\n", char, pos) + } + fmt.Println() + fmt.Println("index int(rune) rune char bytes") + for index, rune := range str2 { + fmt.Printf("%-2d %d %U '%c' % X\n", index, rune, rune, rune, []byte(string(rune))) + } +} +/* Output: +The length of str is: 27 +Character on position 0 is: G +Character on position 1 is: o +Character on position 2 is: +Character on position 3 is: i +Character on position 4 is: s +Character on position 5 is: +Character on position 6 is: a +Character on position 7 is: +Character on position 8 is: b +Character on position 9 is: e +Character on position 10 is: a +Character on position 11 is: u +Character on position 12 is: t +Character on position 13 is: i +Character on position 14 is: f +Character on position 15 is: u +Character on position 16 is: l +Character on position 17 is: +Character on position 18 is: l +Character on position 19 is: a +Character on position 20 is: n +Character on position 21 is: g +Character on position 22 is: u +Character on position 23 is: a +Character on position 24 is: g +Character on position 25 is: e +Character on position 26 is: ! + +The length of str2 is: 18 +character C starts at byte position 0 +character h starts at byte position 1 +character i starts at byte position 2 +character n starts at byte position 3 +character e starts at byte position 4 +character s starts at byte position 5 +character e starts at byte position 6 +character : starts at byte position 7 +character starts at byte position 8 +character 日 starts at byte position 9 +character 本 starts at byte position 12 +character 語 starts at byte position 15 + +index int(rune) rune char bytes +0 67 U+0043 'C' 43 +1 104 U+0068 'h' 68 +2 105 U+0069 'i' 69 +3 110 U+006E 'n' 6E +4 101 U+0065 'e' 65 +5 115 U+0073 's' 73 +6 101 U+0065 'e' 65 +7 58 U+003A ':' 3A +8 32 U+0020 ' ' 20 +9 26085 U+65E5 '日' E6 97 A5 +12 26412 U+672C '本' E6 9C AC +15 35486 U+8A9E '語' E8 AA 9E +*/ diff --git a/eBook/examples/chapter_5/string_conversion2.go b/eBook/examples/chapter_5/string_conversion2.go index 4add5eb..49e9479 100644 --- a/eBook/examples/chapter_5/string_conversion2.go +++ b/eBook/examples/chapter_5/string_conversion2.go @@ -1,25 +1,25 @@ -package main - -import ( - "fmt" - "strconv" -) - -func main() { - var orig string = "ABC" - // var an int - var newS string - // var err error - - fmt.Printf("The size of ints is: %d\n", strconv.IntSize) - // anInt, err = strconv.Atoi(origStr) - an, err := strconv.Atoi(orig) - if err != nil { - fmt.Printf("orig %s is not an integer - exiting with error\n", orig) - return - } - fmt.Printf("The integer is %d\n", an) - an = an + 5 - newS = strconv.Itoa(an) - fmt.Printf("The new string is: %s\n", newS) -} +package main + +import ( + "fmt" + "strconv" +) + +func main() { + var orig string = "ABC" + // var an int + var newS string + // var err error + + fmt.Printf("The size of ints is: %d\n", strconv.IntSize) + // anInt, err = strconv.Atoi(origStr) + an, err := strconv.Atoi(orig) + if err != nil { + fmt.Printf("orig %s is not an integer - exiting with error\n", orig) + return + } + fmt.Printf("The integer is %d\n", an) + an = an + 5 + newS = strconv.Itoa(an) + fmt.Printf("The new string is: %s\n", newS) +} diff --git a/eBook/examples/chapter_5/switch1.go b/eBook/examples/chapter_5/switch1.go index a108596..e5a2fa0 100644 --- a/eBook/examples/chapter_5/switch1.go +++ b/eBook/examples/chapter_5/switch1.go @@ -1,16 +1,16 @@ -package main - -import "fmt" - -func main() { - var num1 int = 100 - - switch num1 { - case 98, 99: - fmt.Println("It's equal to 98") - case 100: - fmt.Println("It's equal to 100") - default: - fmt.Println("It's not equal to 98 or 100") - } -} +package main + +import "fmt" + +func main() { + var num1 int = 100 + + switch num1 { + case 98, 99: + fmt.Println("It's equal to 98") + case 100: + fmt.Println("It's equal to 100") + default: + fmt.Println("It's not equal to 98 or 100") + } +} diff --git a/eBook/examples/chapter_5/switch2.go b/eBook/examples/chapter_5/switch2.go index 4f0afe8..80ccae0 100644 --- a/eBook/examples/chapter_5/switch2.go +++ b/eBook/examples/chapter_5/switch2.go @@ -1,16 +1,16 @@ -package main - -import "fmt" - -func main() { - var num1 int = 7 - - switch { - case num1 < 0: - fmt.Println("Number is negative") - case num1 > 0 && num1 < 10: - fmt.Println("Number is between 0 and 10") - default: - fmt.Println("Number is 10 or greater") - } -} +package main + +import "fmt" + +func main() { + var num1 int = 7 + + switch { + case num1 < 0: + fmt.Println("Number is negative") + case num1 > 0 && num1 < 10: + fmt.Println("Number is between 0 and 10") + default: + fmt.Println("Number is 10 or greater") + } +} diff --git a/eBook/examples/chapter_6/blank_identifier.go b/eBook/examples/chapter_6/blank_identifier.go index 2731645..e0a04d0 100644 --- a/eBook/examples/chapter_6/blank_identifier.go +++ b/eBook/examples/chapter_6/blank_identifier.go @@ -1,15 +1,14 @@ -package main - -import "fmt" - -func main() { - var i1 int - var f1 float32 - i1, _, f1 = ThreeValues() - fmt.Printf("The int: %d, the float: %f \n", i1, f1) -} - -func ThreeValues() (int, int, float32) { - return 5, 6, 7.5 -} - +package main + +import "fmt" + +func main() { + var i1 int + var f1 float32 + i1, _, f1 = ThreeValues() + fmt.Printf("The int: %d, the float; %f\n", i1, f1) +} + +func ThreeValues() (int, int, float32) { + return 5, 6, 7.5 +} diff --git a/eBook/examples/chapter_6/defer.go b/eBook/examples/chapter_6/defer.go new file mode 100644 index 0000000..61c92c8 --- /dev/null +++ b/eBook/examples/chapter_6/defer.go @@ -0,0 +1,17 @@ +package main + +import "fmt" + +func main() { + Function1() +} + +func Function1() { + fmt.Printf("In Function1 at the top\n") + defer Function2() + fmt.Printf("In Function1 at the bottom!\n") +} + +func Function2() { + fmt.Printf("Function2: Deferred until the end of the calling function!") +} diff --git a/eBook/examples/chapter_6/defer_dbconn.go b/eBook/examples/chapter_6/defer_dbconn.go new file mode 100644 index 0000000..3898669 --- /dev/null +++ b/eBook/examples/chapter_6/defer_dbconn.go @@ -0,0 +1,38 @@ +// defer_dbconn.go +package main + +import "fmt" + +func main() { + doDBOperations() +} + +func connectToDB () { + fmt.Println( "ok, connected to db" ) +} + +func disconnectFromDB () { + fmt.Println( "ok, disconnected from db" ) +} + +func doDBOperations() { + connectToDB() + fmt.Println("Defering the database disconnect.") + defer disconnectFromDB() //function called here with defer + fmt.Println("Doing some DB operations ...") + fmt.Println("Oops! some crash or network error ...") + fmt.Println("Returning from function here!") + return //terminate the program + // deferred function executed here just before actually returning, even if there is a return or abnormal termination before +} +/* Output: +ok, connected to db +Defering the database disconnect. +Doing some DB operations ... +Oops! some crash or network error ... +Returning from function here! +ok, disconnected from db +*/ + + + diff --git a/eBook/examples/chapter_6/defer_logvalues.go b/eBook/examples/chapter_6/defer_logvalues.go new file mode 100644 index 0000000..73d3874 --- /dev/null +++ b/eBook/examples/chapter_6/defer_logvalues.go @@ -0,0 +1,19 @@ +// defer_logvalues.go +package main + +import ( + "io" + "log" +) + +func func1(s string) (n int, err error) { + defer func() { + log.Printf("func1(%q) = %d, %v", s, n, err) + }() + return 7, io.EOF +} + +func main() { + func1("Go") +} +// Output: 2011/10/04 10:46:11 func1("Go") = 7, EOF \ No newline at end of file diff --git a/eBook/examples/chapter_6/defer_tracing.go b/eBook/examples/chapter_6/defer_tracing.go new file mode 100644 index 0000000..b524e41 --- /dev/null +++ b/eBook/examples/chapter_6/defer_tracing.go @@ -0,0 +1,22 @@ +package main + +import "fmt" + +func trace(s string) { fmt.Println("entering:", s) } +func untrace(s string) { fmt.Println("leaving:", s) } + +func a() { + trace("a") + defer untrace("a") + fmt.Println("in a") +} + +func b() { + trace("b") + defer untrace("b") + fmt.Println("in b") + a() +} +func main() { + b() +} diff --git a/eBook/examples/chapter_6/defer_tracing2.go b/eBook/examples/chapter_6/defer_tracing2.go new file mode 100644 index 0000000..03972d3 --- /dev/null +++ b/eBook/examples/chapter_6/defer_tracing2.go @@ -0,0 +1,25 @@ +package main + +import "fmt" + +func trace(s string) string { + fmt.Println("entering:", s) + return s +} +func un(s string) { + fmt.Println("leaving:", s) +} + +func a() { + defer un(trace("a")) + fmt.Println("in a") +} + +func b() { + defer un(trace("b")) + fmt.Println("in b") + a() +} +func main() { + b() +} diff --git a/eBook/examples/chapter_6/fibonacci.go b/eBook/examples/chapter_6/fibonacci.go new file mode 100644 index 0000000..d1f6b0d --- /dev/null +++ b/eBook/examples/chapter_6/fibonacci.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + result := 0 + start := time.Now() + for i:=0; i <= 25; i++ { + result = fibonacci(i) + fmt.Printf("fibonacci(%d) is: %d\n", i, result) + } + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} + +func fibonacci(n int) (res int) { + if n <= 1 { + res = 1 + } else { + res = fibonacci(n-1) + fibonacci(n-2) + } + return +} +/* Output: +fibonacci(0) is: 1 +fibonacci(1) is: 1 +fibonacci(2) is: 2 +fibonacci(3) is: 3 +fibonacci(4) is: 5 +fibonacci(5) is: 8 +fibonacci(6) is: 13 +fibonacci(7) is: 21 +fibonacci(8) is: 34 +fibonacci(9) is: 55 +fibonacci(10) is: 89 +fibonacci(11) is: 144 +fibonacci(12) is: 233 +fibonacci(13) is: 377 +fibonacci(14) is: 610 +fibonacci(15) is: 987 +fibonacci(16) is: 1597 +fibonacci(17) is: 2584 +fibonacci(18) is: 4181 +fibonacci(19) is: 6765 +fibonacci(20) is: 10946 +fibonacci(21) is: 17711 +fibonacci(22) is: 28657 +fibonacci(23) is: 46368 +fibonacci(24) is: 75025 +fibonacci(25) is: 121393 +longCalculation took this amount of time: 3.0001ms +*/ diff --git a/eBook/examples/chapter_6/fibonacci_memoization.go b/eBook/examples/chapter_6/fibonacci_memoization.go new file mode 100644 index 0000000..0001de6 --- /dev/null +++ b/eBook/examples/chapter_6/fibonacci_memoization.go @@ -0,0 +1,42 @@ +// fibonacci_memoization.go +package main + +import ( + "fmt" + "time" +) + +const LIM = 41 +var fibs [LIM]uint64 + +func main() { + var result uint64 = 0 + start := time.Now() + for i:=0; i < LIM; i++ { + result = fibonacci(i) + fmt.Printf("fibonacci(%d) is: %d\n", i, result) + } + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} + +func fibonacci(n int) (res uint64) { + // memoization: check if fibonacci(n) is already known in array: + if fibs[n] != 0 { + res = fibs[n] + return + } + if n <= 1 { + res = 1 + } else { + res = fibonacci(n-1) + fibonacci(n-2) + } + fibs[n] = res + return +} +/* +Output: LIM=40: +normal (fibonacci.go): the calculation took this amount of time: 4.730270 s + with memoization: the calculation took this amount of time: 0.001000 s +*/ diff --git a/eBook/examples/chapter_6/filter_factory.go b/eBook/examples/chapter_6/filter_factory.go new file mode 100644 index 0000000..13e6788 --- /dev/null +++ b/eBook/examples/chapter_6/filter_factory.go @@ -0,0 +1,53 @@ +// filter_factory.go +package main +import "fmt" + +type flt func (int) bool +type slice_split func([]int) ([]int, []int) + +func isOdd(integer int) bool{ + if integer%2 == 0 { + return false + } + return true +} + +func isBiggerThan4(integer int) bool{ + if integer > 4 { + return true + } + return false +} + +func filter_factory(f flt) slice_split { + return func(s []int) (yes, no []int){ + for _, val := range s{ + if f(val){ + yes = append(yes, val) + } else { + no = append(no, val) + } + } + return + } +} + +func main(){ + s := []int {1, 2, 3, 4, 5, 7} + fmt.Println("s = ", s) + odd_even_function := filter_factory(isOdd) + odd, even := odd_even_function(s) + fmt.Println("odd = ", odd) + fmt.Println("even = ", even) + //separate those that are bigger than 4 and those that are not. + bigger, smaller := filter_factory(isBiggerThan4)(s) + fmt.Println("Bigger than 4: ", bigger) + fmt.Println("Smaller than or equal to 4: ", smaller) +} +/* +s = [1 2 3 4 5 7] +odd = [1 3 5 7] +even = [2 4] +Bigger than 4: [5 7] +Smaller than or equal to 4: [1 2 3 4] +*/ diff --git a/eBook/examples/chapter_6/function_closure.go b/eBook/examples/chapter_6/function_closure.go new file mode 100644 index 0000000..59104b5 --- /dev/null +++ b/eBook/examples/chapter_6/function_closure.go @@ -0,0 +1,18 @@ +package main + +import "fmt" + +func main() { + var f = Adder() + fmt.Print(f(1)," - ") + fmt.Print(f(20)," - ") + fmt.Print(f(300)) +} + +func Adder() func(int) int { + var x int + return func(delta int) int { + x += delta + return x + } +} diff --git a/eBook/examples/chapter_6/function_filter.go b/eBook/examples/chapter_6/function_filter.go new file mode 100644 index 0000000..fa1a4e7 --- /dev/null +++ b/eBook/examples/chapter_6/function_filter.go @@ -0,0 +1,48 @@ +// function_filter.go +package main +import "fmt" + +type flt func(int) bool + +// isOdd takes an ints and returns a bool set to true if the +// int parameter is odd, or false if not. +// isOdd is of type func(int) bool which is what flt is declared to be. + +func isOdd(n int) bool { + if n%2 == 0 { + return false + } + return true +} + +// Same comment for isEven +func isEven(n int) bool { + if n%2 == 0 { + return true + } + return false +} + +func filter(sl []int, f flt) []int { + var res []int + for _, val := range sl { + if f(val) { + res = append(res, val) + } + } + return res +} + +func main(){ + slice := []int {1, 2, 3, 4, 5, 7} + fmt.Println("slice = ", slice) + odd := filter(slice, isOdd) + fmt.Println("Odd elements of slice are: ", odd) + even := filter(slice, isEven) + fmt.Println("Even elements of slice are: ", even) +} +/* +slice = [1 2 3 4 5 7] +Odd elements of slice are: [1 3 5 7] +Even elements of slice are: [2 4] +*/ diff --git a/eBook/examples/chapter_6/function_literal.go b/eBook/examples/chapter_6/function_literal.go new file mode 100644 index 0000000..ece9faf --- /dev/null +++ b/eBook/examples/chapter_6/function_literal.go @@ -0,0 +1,15 @@ +package main +import "fmt" + +func main() { + f() +} + +func f() { + for i := 0; i < 4; i++ { + g := func(i int) { fmt.Printf("%d ", i) } + g(i) + fmt.Printf(" - g is of type %T and has value %v\n", g, g) + } + +} diff --git a/eBook/examples/chapter_6/function_parameter.go b/eBook/examples/chapter_6/function_parameter.go new file mode 100644 index 0000000..3e2fe40 --- /dev/null +++ b/eBook/examples/chapter_6/function_parameter.go @@ -0,0 +1,20 @@ +// function_parameter.go +package main + +import ( + "fmt" +) + +func main() { + callback(1, Add) +} + +func Add(a,b int) { + fmt.Printf("The sum of %d and %d is: %d\n", a, b, a + b) +} + + +func callback(y int, f func(int, int)) { + f(y, 2) // this becomes Add(1, 2) +} +// Output: The sum of 1 and 2 is: 3 diff --git a/eBook/examples/chapter_6/function_return.go b/eBook/examples/chapter_6/function_return.go new file mode 100644 index 0000000..4d4c72d --- /dev/null +++ b/eBook/examples/chapter_6/function_return.go @@ -0,0 +1,27 @@ +package main +import "fmt" + +func main() { + // make an Add2 function, give it a name p2, and call it: + p2 := Add2() + fmt.Printf("Call Add2 for 2 gives: %v\n", p2(2)) + // make a special Adder function, a gets value 2: + TwoAdder := Adder(2) + fmt.Printf("The result is: %v\n", TwoAdder(2)) +} + +func Add2() (func(b int) int) { + return func(b int) int { + return b + 2 + } +} + +func Adder(a int) (func(b int) int) { + return func(b int) int { + return a + b + } +} +/* Output: +Call Add2 for 2 gives: 4 +The result is: 4 +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_6/greeting.go b/eBook/examples/chapter_6/greeting.go index 10902da..493a00f 100644 --- a/eBook/examples/chapter_6/greeting.go +++ b/eBook/examples/chapter_6/greeting.go @@ -1,11 +1,11 @@ -package main - -func main() { - println("In main before calling greeting") - greeting() - println("In main after calling greeting") -} - -func greeting() { - println("In greeting: Hi!!!!!") -} \ No newline at end of file +package main + +func main() { + println("In main before calling greeting") + greeting() + println("In main after calling greeting") +} + +func greeting() { + println("In greeting: Hi!!!!!") +} diff --git a/eBook/examples/chapter_6/minmax.go b/eBook/examples/chapter_6/minmax.go index 0ccbfb8..f0dc134 100644 --- a/eBook/examples/chapter_6/minmax.go +++ b/eBook/examples/chapter_6/minmax.go @@ -1,20 +1,20 @@ -package main - -import "fmt" - -func main() { - var min, max int - min, max = MinMax(78, 65) - fmt.Printf("Minmium is: %d, Maximum is: %d\n", min, max) -} - -func MinMax(a int, b int) (min int, max int) { - if a < b { - min = a - max = b - } else { // a = b or a < b - min = b - max = a - } - return +package main + +import "fmt" + +func main() { + var min, max int + min, max = MinMax(78, 65) + fmt.Printf("Minimum is: %d, Maximum is: %d\n", min, max) +} + +func MinMax(a int, b int) (min int, max int) { + if a < b { + min = a + max = b + } else { // a = b or a < b + min = b + max = a + } + return } \ No newline at end of file diff --git a/eBook/examples/chapter_6/multiple_return.go b/eBook/examples/chapter_6/multiple_return.go index e1dea97..22304d5 100644 --- a/eBook/examples/chapter_6/multiple_return.go +++ b/eBook/examples/chapter_6/multiple_return.go @@ -1,28 +1,28 @@ -package main - -import "fmt" - -var num int = 10 -var numx2, numx3 int - -func main() { - numx2, numx3 = getX2AndX3(num) - PrintValues() - numx2, numx3 = getX2AndX3_2(num) - PrintValues() -} - -func PrintValues() { - fmt.Printf("num = %d, 2x num = %d, 3x num = %d\n", num, numx2, numx3) -} - -func getX2AndX3(input int) (int, int) { - return 2 * input, 3 * input -} - -func getX2AndX3_2(input int) (x2 int, x3 int) { - x2 = 2 * input - x3 = 3 * input - // return x2, x3 - return -} \ No newline at end of file +package main + +import "fmt" + +var num int = 10 +var numx2, numx3 int + +func main() { + numx2, numx3 = getX2AndX3(num) + PrintValues() + numx2, numx3 = getX2AndX3_2(num) + PrintValues() +} + +func PrintValues() { + fmt.Printf("num = %d, 2x num = %d, 3x num = %d\n", num, numx2, numx3) +} + +func getX2AndX3(input int) (int, int) { + return 2 * input, 3 * input +} + +func getX2AndX3_2(input int) (x2 int, x3 int) { + x2 = 2 * input + x3 = 3 * input + // return x2, x3 + return +} diff --git a/eBook/examples/chapter_6/mut_recurs.go b/eBook/examples/chapter_6/mut_recurs.go new file mode 100644 index 0000000..cc9a8f4 --- /dev/null +++ b/eBook/examples/chapter_6/mut_recurs.go @@ -0,0 +1,27 @@ +// mut_recurs.go +package main + +import ( + "fmt" +) + +func main() { + fmt.Printf("%d is even: is %t\n", 16, even(16)) // 16 is even: is true + fmt.Printf("%d is odd: is %t\n", 17, odd(17)) // 17 is odd: is true + fmt.Printf("%d is odd: is %t\n", 18, odd(18)) // 18 is odd: is false +} + +func even(nr int) bool { + if nr == 0 {return true} + return odd(RevSign(nr)-1) +} + +func odd(nr int) bool { + if nr == 0 {return false} + return even(RevSign(nr)-1) +} + +func RevSign(nr int) int { + if nr < 0 {return -nr} + return nr +} \ No newline at end of file diff --git a/eBook/examples/chapter_6/return_defer.go b/eBook/examples/chapter_6/return_defer.go new file mode 100644 index 0000000..b6a82c7 --- /dev/null +++ b/eBook/examples/chapter_6/return_defer.go @@ -0,0 +1,18 @@ +// test_defer.go +package main + +import ( + "fmt" +) + +func f() (ret int) { + defer func() { + ret++ + }() + return 1 +} + +func main() { + fmt.Println(f()) +} +// Output: 2 diff --git a/eBook/examples/chapter_6/side_effect.go b/eBook/examples/chapter_6/side_effect.go index 700d44f..7c7c055 100644 --- a/eBook/examples/chapter_6/side_effect.go +++ b/eBook/examples/chapter_6/side_effect.go @@ -1,17 +1,18 @@ -package main - -import ( - "fmt" -) - -// this function changes reply: -func Multiply(a, b int, reply *int) { - *reply = a * b -} - -func main() { - n := 0 - reply := &n - Multiply(10, 5, reply) - fmt.Println("Multiply:", *reply) // Multiply: 50 -} \ No newline at end of file +// side_effect.go +package main + +import ( + "fmt" +) + +func Multiply(a, b int, reply *int) { + *reply = a * b +} + +func main() { + n := 0 + reply := &n + Multiply(10, 5, reply) + fmt.Println("Multiply:", *reply) // Multiply: 50 + fmt.Println("Multiply:", n) // Multiply: 50 +} diff --git a/eBook/examples/chapter_6/simple_function.go b/eBook/examples/chapter_6/simple_function.go index deb2e30..3318f96 100644 --- a/eBook/examples/chapter_6/simple_function.go +++ b/eBook/examples/chapter_6/simple_function.go @@ -1,15 +1,15 @@ -package main - -import "fmt" - -func main() { - fmt.Printf("Multiply 2 * 5 * 6 = %d\n", MultiPly3Nums(2, 5, 6)) - // var i1 int = MultiPly3Nums(2, 5, 6) - // fmt.Printf("MultiPly 2 * 5 * 6 = %d\n", i1) -} - -func MultiPly3Nums(a int, b int, c int) int { - // var product int = a * b * c - // return product - return a * b * c -} \ No newline at end of file +package main + +import "fmt" + +func main() { + var i1 int = MultiPly3Nums(2, 5, 6) + fmt.Printf("Multiply 2 * 5 * 6 = %d\n", i1) + // fmt.Printf("Multiply 2 * 5 * 6 = %d\n", MultiPly3Nums(2, 5, 6)) +} + +func MultiPly3Nums(a int, b int, c int) int { + // var product int = a * b * c + // return product + return a * b * c +} diff --git a/eBook/examples/chapter_6/varnumpar.go b/eBook/examples/chapter_6/varnumpar.go new file mode 100644 index 0000000..2e78470 --- /dev/null +++ b/eBook/examples/chapter_6/varnumpar.go @@ -0,0 +1,28 @@ +package main + +import "fmt" + +func main() { + x := Min(1, 3, 2, 0) + fmt.Printf("The minimum is: %d\n", x) + arr := []int{7,9,3,5,1} + x = Min(arr...) + fmt.Printf("The minimum in the array arr is: %d", x) +} + +func Min(a ...int) int { + if len(a)==0 { + return 0 + } + min := a[0] + for _, v := range a { + if v < min { + min = v + } + } + return min +} +/* +The minimum is: 0 +The minimum in the array arr is: 1 +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_7/array_literals.go b/eBook/examples/chapter_7/array_literals.go index 5b9ad34..63e8997 100644 --- a/eBook/examples/chapter_7/array_literals.go +++ b/eBook/examples/chapter_7/array_literals.go @@ -1,14 +1,24 @@ -package main -import "fmt" - -func main() { - // var arrAge = [5]int{18, 20, 15, 22, 16} - // var arrLazy = [...]int{5, 6, 7, 8, 22} - // var arrLazy = []int{5, 6, 7, 8, 22} - var arrKeyValue = [5]string{3: "Chris", 4: "Ron"} - // var arrKeyValue = []string{3: "Chris", 4: "Ron"} - - for i:=0; i < len(arrKeyValue); i++ { - fmt.Printf("Person at %d is %s\n", i, arrKeyValue[i]) - } -} +package main + +import "fmt" + +func main() { + var arrAge = [5]int{18, 20, 15, 22, 16} + var arrLazy = [...]int{5, 6, 7, 8, 22} + // var arrLazy = []int{5, 6, 7, 8, 22} + var arrKeyValue = [5]string{3: "Chris", 4: "Ron"} + //var arrKeyValue = []string{3: "Chris", 4: "Ron"} + for i := 0; i < len(arrAge); i++ { + fmt.Printf("Age at %d is %d\n", i, arrAge[i]) + } + fmt.Println() + + for i := 0; i < len(arrLazy); i++ { + fmt.Printf("Number at %d is %d\n", i, arrLazy[i]) + } + fmt.Printf("\n") + + for i := 0; i < len(arrKeyValue); i++ { + fmt.Printf("Person at %d is %s\n", i, arrKeyValue[i]) + } +} diff --git a/eBook/examples/chapter_7/array_slices.go b/eBook/examples/chapter_7/array_slices.go index de3ffdc..9b1bf12 100644 --- a/eBook/examples/chapter_7/array_slices.go +++ b/eBook/examples/chapter_7/array_slices.go @@ -1,32 +1,33 @@ -package main -import "fmt" - -func main() { - var arr1 [6]int - var slice1 []int = arr1[2:5] // item at index 5 not included! - - // load the array with integers: 0,1,2,3,4,5 - for i := 0; i < len(arr1); i++ { - arr1[i] = i - } - - // print the slice - for i := 0; i < len(slice1); i++ { - fmt.Printf("Slice at %d is %d\n", i, slice1[i]) - } - - fmt.Printf("The length of arr1 is %d\n", len(arr1)) - fmt.Printf("The length of slice1 is %d\n", len(slice1)) - fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) - -// grow the slice - slice1 = slice1[0:4] - for i := 0; i < len(slice1); i++ { - fmt.Printf("Slice at %d is %d\n", i, slice1[i]) - } - fmt.Printf("The length of slice1 is %d\n", len(slice1)) - fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) - -// grow the slice beyond capacity - //slice1 = slice1[0:7 ] // panic: runtime error: slice bound out of range -} +package main + +import "fmt" + +func main() { + var arr1 [6]int + var slice1 []int = arr1[2:5] // index 5 niet meegerekend! + + // load the array with integers: 0,1,2,3,4,5 + for i := 0; i < len(arr1); i++ { + arr1[i] = i + } + + // print the slice: + for i := 0; i < len(slice1); i++ { + fmt.Printf("Slice at %d is %d\n", i, slice1[i]) + } + + fmt.Printf("The length of arr1 is %d\n", len(arr1)) + fmt.Printf("The length of slice1 is %d\n", len(slice1)) + fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) + + // grow the slice: + slice1 = slice1[0:4] + for i := 0; i < len(slice1); i++ { + fmt.Printf("Slice at %d is %d\n", i, slice1[i]) + } + fmt.Printf("The length of slice1 is %d\n", len(slice1)) + fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) + + // grow the slice beyond capacity: + // slice1 = slice1[0:7 ] // panic: runtime error: slice bounds out of range +} diff --git a/eBook/examples/chapter_7/array_sum.go b/eBook/examples/chapter_7/array_sum.go index a1a3a7f..2f33720 100644 --- a/eBook/examples/chapter_7/array_sum.go +++ b/eBook/examples/chapter_7/array_sum.go @@ -1,16 +1,17 @@ -package main -import "fmt" - -func main() { - array := [3]float64{7.0, 8.5, 9.1} - x := Sum(&array) // Note the explicit address-of operator - // to pass a pointer to the array - fmt.Printf("The sum of the array is: %f", x) -} - -func Sum(a *[3]float64) (sum float64) { - for _, v := range a { // derefencing *a to get back to the array is not necessary! - sum += v - } - return -} +package main + +import "fmt" + +func main() { + array := [3]float64{7.0, 8.5, 9.1} + x := Sum(&array) // Note the explicit address-of operator to pass a pointer to the array + fmt.Printf("The sum of the array is: %f", x) +} + +func Sum(a *[3]float64) (sum float64) { + for _, v := range a { // can also with dereferencing *a to get back to the array + sum += v + } + return +} +// Output: The sum of the array is: 24.600000 diff --git a/eBook/examples/chapter_7/copy_append_slice.go b/eBook/examples/chapter_7/copy_append_slice.go index a20a291..f9cb3b6 100644 --- a/eBook/examples/chapter_7/copy_append_slice.go +++ b/eBook/examples/chapter_7/copy_append_slice.go @@ -1,15 +1,16 @@ -package main -import "fmt" - -func main() { - sl_from := []int{1, 2, 3} - sl_to := make([]int, 10) - - n := copy(sl_to, sl_from) - fmt.Println(sl_to) - fmt.Printf("Copied %d elements\n", n) // n == 3 - - sl3 := []int{1, 2, 3} - sl3 = append(sl3, 4, 5, 6) - fmt.Println(sl3) -} +package main + +import "fmt" + +func main() { + sl_from := []int{1,2,3} + sl_to := make([]int,10) + + n := copy(sl_to, sl_from) + fmt.Println(sl_to) // output: [1 2 3 0 0 0 0 0 0 0] + fmt.Printf("Copied %d elements\n", n) // n == 3 + + sl3 := []int{1,2,3} + sl3 = append(sl3, 4, 5, 6) + fmt.Println(sl3) // output: [1 2 3 4 5 6] +} diff --git a/eBook/examples/chapter_7/for_arrays.go b/eBook/examples/chapter_7/for_arrays.go index f5a6239..f7182aa 100644 --- a/eBook/examples/chapter_7/for_arrays.go +++ b/eBook/examples/chapter_7/for_arrays.go @@ -1,14 +1,16 @@ -package main -import "fmt" - -func main() { - var arr1 [5]int - - for i:=0; i < len(arr1); i++ { - arr1[i] = i * 2 - } - - for i:=0; i < len(arr1); i++ { - fmt.Printf("Array at index %d is %d\n", i, arr1[i]) - } -} +package main + +import "fmt" + +func main() { + var arr1 [5]int + // var arr1 = new([5]int) + + for i:=0; i < len(arr1); i++ { + arr1[i] = i * 2 + } + + for i:=0; i < len(arr1); i++ { + fmt.Printf("Array at index %d is %d\n", i, arr1[i]) + } +} \ No newline at end of file diff --git a/eBook/examples/chapter_7/for_string.go b/eBook/examples/chapter_7/for_string.go new file mode 100644 index 0000000..23cfb7b --- /dev/null +++ b/eBook/examples/chapter_7/for_string.go @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + s := "\u00ff\u754c" + for i, c := range s { + fmt.Printf("%d:%c ", i, c) + } +} +// prints: 0:ÿ 2:界 \ No newline at end of file diff --git a/eBook/examples/chapter_7/make_slice.go b/eBook/examples/chapter_7/make_slice.go index f7d9bf4..321e535 100644 --- a/eBook/examples/chapter_7/make_slice.go +++ b/eBook/examples/chapter_7/make_slice.go @@ -1,17 +1,18 @@ -package main -import "fmt" - -func main() { - var slice1 []int = make([]int, 10) - // load the array/slice: - for i := 0; i < len(slice1); i++ { - slice1[i] = 5 * i - } - - // print the slice: - for i := 0; i < len(slice1); i++ { - fmt.Printf("Slice at %d is %d\n", i, slice1[i]) - } - fmt.Printf("\nThe length of slice1 is %d\n", len(slice1)) - fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) -} +package main + +import "fmt" + +func main() { + // var slice1 []int = make([]int, 10) + slice1 := make([]int, 10) + // load the array/slice: + for i := 0; i < len(slice1); i++ { + slice1[i] = 5 * i + } + // print the slice: + for i := 0; i < len(slice1); i++ { + fmt.Printf("Slice at %d is %d\n", i, slice1[i]) + } + fmt.Printf("\nThe length of slice1 is %d\n", len(slice1)) + fmt.Printf("The capacity of slice1 is %d\n", cap(slice1)) +} diff --git a/eBook/examples/chapter_7/multidim_array.go b/eBook/examples/chapter_7/multidim_array.go index c787ec2..b73d732 100644 --- a/eBook/examples/chapter_7/multidim_array.go +++ b/eBook/examples/chapter_7/multidim_array.go @@ -1,16 +1,35 @@ -package main -const ( - WIDTH = 1920 - HEIGHT = 1080 -) - -type pixel int -var screen [WIDTH][HEIGHT]pixel - -func main() { - for y := 0; y < HEIGHT; y++ { - for x := 0; x < WIDTH; x++ { - screen[x][y] = 0 - } - } -} +// multidim_array.go +package main + +import "fmt" + +const ( + WIDTH = 1920 + HEIGHT = 1080 + // WIDTH = 5 + // HEIGHT = 4 +) + +type pixel int +var screen [WIDTH][HEIGHT]pixel + +func main() { + for y := 0; y < HEIGHT; y++ { + for x := 0; x < WIDTH; x++ { + screen[x][y] = 0 + } + } + fmt.Println(screen) + + for row := range screen { + for column := range screen[0] { + screen[row][column] = 1 + } + } + + fmt.Println(screen) +} +/* Output for WIDTH = 5 and HEIGHT = 4: +[[0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0]] +[[1 1 1 1] [1 1 1 1] [1 1 1 1] [1 1 1 1] [1 1 1 1]] +*/ diff --git a/eBook/examples/chapter_7/pointer_array.go b/eBook/examples/chapter_7/pointer_array.go index 6f5e9a4..2cd1487 100644 --- a/eBook/examples/chapter_7/pointer_array.go +++ b/eBook/examples/chapter_7/pointer_array.go @@ -1,10 +1,12 @@ -package main -import "fmt" -func f(a [3]int) { fmt.Println(a) } -func fp(a *[3]int) { fmt.Println(a) } - -func main() { - var ar [3]int - f(ar) // passes a copy of ar - fp(&ar) // passes a pointer to ar -} +package main + +import "fmt" + +func f(a [3]int) { fmt.Println(a) } +func fp(a *[3]int) { fmt.Println(a) } + +func main() { + var ar [3]int + f(ar) // passes a copy of ar + fp(&ar) // passes a pointer to ar +} diff --git a/eBook/examples/chapter_7/pointer_array2.go b/eBook/examples/chapter_7/pointer_array2.go index 0096720..4816f89 100644 --- a/eBook/examples/chapter_7/pointer_array2.go +++ b/eBook/examples/chapter_7/pointer_array2.go @@ -1,10 +1,11 @@ -package main -import "fmt" - -func fp(a *[3]int) { fmt.Println(a) } - -func main() { - for i := 0; i < 3; i++ { - fp(&[3]int{i, i * i, i * i * i}) - } -} +package main + +import "fmt" + +func fp(a *[3]int) { fmt.Println(a) } + +func main() { + for i := 0; i < 3; i++ { + fp(&[3]int{i, i * i, i * i * i}) + } +} diff --git a/eBook/examples/chapter_7/reslicing.go b/eBook/examples/chapter_7/reslicing.go index 87fe45d..a34a4e0 100644 --- a/eBook/examples/chapter_7/reslicing.go +++ b/eBook/examples/chapter_7/reslicing.go @@ -1,17 +1,18 @@ -package main -import "fmt" - -func main() { - slice1 := make([]int, 0, 10) - // load the slice, cap(slice1) is 10: - for i := 0; i < cap(slice1); i++ { - slice1 = slice1[0:i+1] - slice1[i] = i - fmt.Printf("The length of slice is %d\n", len(slice1)) - } - - // print the slice: - for i := 0; i < len(slice1); i++ { - fmt.Printf("Slice at %d is %d\n", i, slice1[i]) - } -} +package main + +import "fmt" + +func main() { + //var slice1 []int = make([]int, 0, 10) + slice1 := make([]int, 0, 10) + // load the slice, cap(slice1) is 10: + for i := 0; i < cap(slice1); i++ { + slice1 = slice1[0:i+1] // reslice + slice1[i] = i + fmt.Printf("The length of slice is %d\n", len(slice1)) + } + // print the slice: + for i := 0; i < len(slice1); i++ { + fmt.Printf("Slice at %d is %d\n", i, slice1[i]) + } +} diff --git a/eBook/examples/chapter_7/slices_forrange.go b/eBook/examples/chapter_7/slices_forrange.go index 772a663..6ffb374 100644 --- a/eBook/examples/chapter_7/slices_forrange.go +++ b/eBook/examples/chapter_7/slices_forrange.go @@ -1,15 +1,22 @@ -package main -import "fmt" - -func main() { - slice1 := make([]int, 4) - - slice1[0] = 1 - slice1[0] = 2 - slice1[0] = 3 - slice1[0] = 4 - - for ix, value := range slice1 { - fmt.Printf("Slice at %d is: %d\n", ix, value) - } -} +package main + +import "fmt" + +func main() { + var slice1 []int = make([]int, 4) + + slice1[0] = 1 + slice1[1] = 2 + slice1[2] = 3 + slice1[3] = 4 + + for ix, value := range slice1 { + fmt.Printf("Slice at %d is: %d\n", ix, value) + } +} +/* +Slice at 0 is: 1 +Slice at 1 is: 2 +Slice at 2 is: 3 +Slice at 3 is: 4 +*/ diff --git a/eBook/examples/chapter_7/slices_forrange2.go b/eBook/examples/chapter_7/slices_forrange2.go index e68a121..365573e 100644 --- a/eBook/examples/chapter_7/slices_forrange2.go +++ b/eBook/examples/chapter_7/slices_forrange2.go @@ -1,14 +1,31 @@ -package main -import "fmt" - -func main() { - seasons := []string{"Spring", "Summer", "Autumn", "Winter"} - for ix, season := range seasons { - fmt.Printf("Season %d is: %s\n", ix, season) - } - - var season string - for _, season = range seasons { - fmt.Printf("%s\n", season) - } -} +package main + +import "fmt" + +func main() { + seasons := []string{"Spring","Summer","Autumn","Winter"} + + for ix, season := range seasons { + fmt.Printf("Season %d is: %s\n", ix, season) + } + + var season string + for _, season = range seasons { + fmt.Printf("%s\n", season) + } + + for ix := range seasons { + fmt.Printf("%d ", ix) + } +} +/* Output: +Season 0 is: Spring +Season 1 is: Summer +Season 2 is: Autumn +Season 3 is: Winter +Spring +Summer +Autumn +Winter +0 1 2 3 +*/ diff --git a/eBook/examples/chapter_8/Makefile.txt b/eBook/examples/chapter_8/Makefile.txt new file mode 100644 index 0000000..ecfff55 --- /dev/null +++ b/eBook/examples/chapter_8/Makefile.txt @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc +TARG=pack1 +GOFILES=\ + pack1.go\ + pack1b.go\ + +include $(GOROOT)/src/Make.pkg diff --git a/eBook/examples/chapter_8/invert_map.go b/eBook/examples/chapter_8/invert_map.go index 69007e0..12eab02 100644 --- a/eBook/examples/chapter_8/invert_map.go +++ b/eBook/examples/chapter_8/invert_map.go @@ -1,23 +1,29 @@ -package main -import ( - "fmt" -) - -var ( - barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23, - "delta": 87, "echo": 56, "foxtrot": 12, - "golf": 34, "hotel": 16, "indio": 87, - "juliet": 65, "kili": 43, "lima": 98} -) - -func main() { - invMap := make(map[int]string, len(barVal)) - for k, v := range barVal { - invMap[v] = k - } - fmt.Println("inverted:") - for k, v := range invMap { - fmt.Printf("Key: %v, Value: %v / ", k, v) - } - fmt.Println() -} +// invert_map.go +package main + +import ( + "fmt" +) + +var ( + barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23, "delta": 87, + "echo": 56, "foxtrot": 12, "golf": 34, "hotel": 16, "indio": 87, "juliet": 65, "kilo": 43, "lima": 98} +) + +func main() { + invMap := make(map[int]string, len(barVal)) + for k, v := range barVal { + invMap[v] = k + } + fmt.Println("inverted:") + for k, v := range invMap { + fmt.Printf("Key: %v, Value: %v / ", k, v) + } +} +/* Output: +inverted: +Key: 12, Value: foxtrot / Key: 16, Value: hotel / Key: 87, Value: delta / Key: 23, Value: charlie / +Key: 65, Value: juliet / Key: 43, Value: kilo / Key: 56, Value: bravo / Key: 98, Value: lima / +Key: 34, Value: golf / +*/ + diff --git a/eBook/examples/chapter_8/make_maps.go b/eBook/examples/chapter_8/make_maps.go index 70de8a1..f5eec5e 100644 --- a/eBook/examples/chapter_8/make_maps.go +++ b/eBook/examples/chapter_8/make_maps.go @@ -1,21 +1,28 @@ package main + import "fmt" func main() { - var mapLit map[string]int - //var mapCreated map[string]float32 - var mapAssigned map[string]int + var mapLit map[string]int + //var mapCreated map[string]float32 + var mapAssigned map[string]int - mapLit = map[string]int{"one": 1, "two": 2} - mapCreated := make(map[string]float32) - mapAssigned = mapLit + mapLit = map[string]int{"one": 1, "two": 2} + mapCreated := make(map[string]float32) + mapAssigned = mapLit - mapCreated["key1"] = 4.5 - mapCreated["key2"] = 3.14159 - mapAssigned["two"] = 3 + mapCreated["key1"] = 4.5 + mapCreated["key2"] = 3.14159 + mapAssigned["two"] = 3 - fmt.Printf("Map literal at \"one\" is: %d\n", mapLit["one"]) - fmt.Printf("Map created at \"key2\" is: %f\n", mapCreated["key2"]) - fmt.Printf("Map assigned at \"two\" is: %d\n", mapLit["two"]) - fmt.Printf("Map literal at \"ten\" is: %d\n", mapLit["ten"]) + fmt.Printf("Map literal at \"one\" is: %d\n", mapLit["one"]) + fmt.Printf("Map created at \"key2\" is: %f\n", mapCreated["key2"]) + fmt.Printf("Map assigned at \"two\" is: %d\n", mapLit["two"]) + fmt.Printf("Map literal at \"ten\" is: %d\n", mapLit["ten"]) } +/* Output: +Map literal at "one" is: 1 +Map created at "key2" is: 3.141590 +Map assigned at "two" is: 3 +Map literal at "ten" is: 0 +*/ diff --git a/eBook/examples/chapter_8/map_func.go b/eBook/examples/chapter_8/map_func.go index 954975c..c1fe4a2 100644 --- a/eBook/examples/chapter_8/map_func.go +++ b/eBook/examples/chapter_8/map_func.go @@ -1,11 +1,13 @@ -package main -import "fmt" - -func main() { - mf := map[int]func() int{ - 1: func() int { return 10 }, - 2: func() int { return 20 }, - 5: func() int { return 50 }, - } - fmt.Println(mf) -} +// map_func.go +package main +import "fmt" + +func main() { + mf := map[int]func() int{ + 1: func() int { return 10 }, + 2: func() int { return 20 }, + 5: func() int { return 50 }, + } + fmt.Println(mf) +} +// Output: map[1:0x10903be0 5:0x10903ba0 2:0x10903bc0] diff --git a/eBook/examples/chapter_8/map_testelement.go b/eBook/examples/chapter_8/map_testelement.go index 88449b0..35ff35b 100644 --- a/eBook/examples/chapter_8/map_testelement.go +++ b/eBook/examples/chapter_8/map_testelement.go @@ -1,31 +1,33 @@ -package main -import "fmt" - -func main() { - var value int - var isPresent bool - - map1 := make(map[string]int) - map1["New Delhi"] = 55 - map1["Beijing"] = 20 - map1["Washington"] = 25 - value, isPresent = map1["Beijing"] - if isPresent { - fmt.Printf("The value of \"Beijin\" in map1 is: %d\n", value) - } else { - fmt.Printf("map1 does not contain Beijing") - } - - value, isPresent = map1["Paris"] - fmt.Printf("Is \"Paris\" in map1 ?: %t\n", isPresent) - fmt.Printf("Value is: %d\n", value) - - // delete an item: - delete(map1, "Washington") - value, isPresent = map1["Washington"] - if isPresent { - fmt.Printf("The value of \"Washington\" in map1 is: %d\n", value) - } else { - fmt.Println("map1 does not contain Washington") - } -} +package main + +import "fmt" + +func main() { + var value int + var isPresent bool + + map1 := make(map[string]int) + map1["New Delhi"] = 55 + map1["Bejing"] = 20 + map1["Washington"] = 25 + + value, isPresent = map1["Bejing"] + if isPresent { + fmt.Printf("The value of \"Bejing\" in map1 is: %d\n", value) + } else { + fmt.Println("map1 does not contain Bejing") + } + + value, isPresent = map1["Paris"] + fmt.Printf("Is \"Paris\" in map1 ?: %t\n", isPresent) + fmt.Printf("Value is: %d\n", value) + + // delete an item: + delete(map1, "Washington") + value, isPresent = map1["Washington"] + if isPresent { + fmt.Printf("The value of \"Washington\" in map1 is: %d\n", value) + } else { + fmt.Println("map1 does not contain Washington") + } +} diff --git a/eBook/examples/chapter_8/maps_forrange.go b/eBook/examples/chapter_8/maps_forrange.go index 309d0fa..8a2b84e 100644 --- a/eBook/examples/chapter_8/maps_forrange.go +++ b/eBook/examples/chapter_8/maps_forrange.go @@ -1,13 +1,15 @@ -package main -import "fmt" - -func main() { - map1 := make(map[int]float32) - map1[1] = 1.0 - map1[2] = 2.0 - map1[3] = 3.0 - map1[4] = 4.0 - for key, value := range map1 { - fmt.Printf("key is: %d - value is: %f\n", key, value) - } -} +package main + +import "fmt" + +func main() { + map1 := make(map[int]float32) + map1[1] = 1.0 + map1[2] = 2.0 + map1[3] = 3.0 + map1[4] = 4.0 + + for key, value := range map1 { + fmt.Printf("key is: %d - value is: %f\n", key, value) + } +} diff --git a/eBook/examples/chapter_8/slice_maps.go b/eBook/examples/chapter_8/slice_maps.go index 203b72a..ccc17e8 100644 --- a/eBook/examples/chapter_8/slice_maps.go +++ b/eBook/examples/chapter_8/slice_maps.go @@ -1,20 +1,27 @@ -package main -import "fmt" - -func main() { - // Version A: - items := make([]map[int]int, 5) - for i:= range items { - items[i] = make(map[int]int, 1) - items[i][1] = 2 - } - fmt.Printf("Version A: Value of items: %v\n", items) - - // Version B: NOT GOOD! - items2 := make([]map[int]int, 5) - for _, item := range items2 { - item = make(map[int]int, 1) // item is only a copy of the slice element. - item[1] = 2 // This 'item' will be lost on the next iteration. - } - fmt.Printf("Version B: Value of items: %v\n", items2) -} +// slice_maps.go +package main + +import ( + "fmt" +) + +func main() { +// Version A: + items := make([]map[int]int, 5) + for i := range items { + items[i] = make(map[int]int, 1) + items[i][1] = 2 + } + fmt.Printf("Version A: Value of items: %v\n", items) +// Version B: + items2 := make([]map[int]int, 5) + for _, item := range items2 { + item = make(map[int]int, 1) // item is only a copy of the slice element. + item[1] = 2 // This 'item' will be lost on the next iteration. + } + fmt.Printf("Version B: Value of items: %v\n", items2) +} +/* Output: +Version A: Value of items: [map[1:2] map[1:2] map[1:2] map[1:2] map[1:2]] +Version B: Value of items: [map[] map[] map[] map[] map[]] +*/ diff --git a/eBook/examples/chapter_8/sort_map.go b/eBook/examples/chapter_8/sort_map.go index db34f23..976c5a8 100644 --- a/eBook/examples/chapter_8/sort_map.go +++ b/eBook/examples/chapter_8/sort_map.go @@ -1,32 +1,43 @@ -// the telephone alphabet: -package main -import ( - "fmt" - "sort" -) - -var ( - barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23, - "delta": 87, "echo": 56, "foxtrot": 12, - "golf": 34, "hotel": 16, "indio": 87, - "juliet": 65, "kili": 43, "lima": 98} -) - -func main() { - fmt.Println("unsorted:") - for k, v := range barVal { - fmt.Printf("Key: %v, Value: %v / ", k, v) - } - keys := make([]string, len(barVal)) - i := 0 - for k, _ := range barVal { - keys[i] = k - i++ - } - sort.Strings(keys) - fmt.Println() - fmt.Println("sorted:") - for _, k := range keys { - fmt.Printf("Key: %v, Value: %v / ", k, barVal[k]) - } -} +// sort_map.go +// the telephone alphabet: +package main + +import ( + "fmt" + "sort" +) + +var ( + barVal = map[string]int{"alpha": 34, "bravo": 56, "charlie": 23, "delta": 87, + "echo": 56, "foxtrot": 12, "golf": 34, "hotel": 16, "indio": 87, "juliet": 65, "kilo": 43, "lima": 98} +) + +func main() { + fmt.Println("unsorted:") + for k, v := range barVal { + fmt.Printf("Key: %v, Value: %v / ", k, v) + } + keys := make([]string, len(barVal)) + i := 0 + for k, _ := range barVal { + keys[i] = k + i++ + } + sort.Strings(keys) + fmt.Println() + fmt.Println("sorted:") + for _, k := range keys { + fmt.Printf("Key: %v, Value: %v / ", k, barVal[k]) + } +} +/* Output: +unsorted: +Key: indio, Value: 87 / Key: echo, Value: 56 / Key: juliet, Value: 65 / Key: charlie, Value: 23 / +Key: hotel, Value: 16 / Key: lima, Value: 98 / Key: bravo, Value: 56 / Key: alpha, Value: 34 / +Key: kilo, Value: 43 / Key: delta, Value: 87 / Key: golf, Value: 34 / Key: foxtrot, Value: 12 / +sorted: +Key: alpha, Value: 34 / Key: bravo, Value: 56 / Key: charlie, Value: 23 / Key: delta, Value: 87 / +Key: echo, Value: 56 / Key: foxtrot, Value: 12 / Key: golf, Value: 34 / Key: hotel, Value: 16 / +Key: indio, Value: 87 / Key: juliet, Value: 65 / Key: kilo, Value: 43 / Key: lima, Value: 98 / +*/ + diff --git a/eBook/examples/chapter_9/big.go b/eBook/examples/chapter_9/big.go new file mode 100644 index 0000000..22bc559 --- /dev/null +++ b/eBook/examples/chapter_9/big.go @@ -0,0 +1,30 @@ +// big.go +package main + +import ( + "math" + "math/big" + "fmt" +) + +func main() { +// Here are some calculations with bigInts: + im := big.NewInt(math.MaxInt64) + in := im + io := big.NewInt(1956) + ip := big.NewInt(1) + ip.Mul(im, in).Add(ip, im).Div(ip, io) + fmt.Printf("Big Int: %v\n", ip) +// Here are some calculations with bigInts: + rm := big.NewRat(math.MaxInt64, 1956) + rn := big.NewRat(-1956, math.MaxInt64) + ro := big.NewRat(19, 56) + rp := big.NewRat(1111, 2222) + rq := big.NewRat(1, 1) + rq.Mul(rm, rn).Add(rq, ro).Mul(rq, rp) + fmt.Printf("Big Rat: %v\n", rq) +} +/* Output: +Big Int: 43492122561469640008497075573153004 +Big Rat: -37/112 +*/ diff --git a/eBook/examples/chapter_9/book/book_main/main.go b/eBook/examples/chapter_9/book/book_main/main.go new file mode 100644 index 0000000..503bc2d --- /dev/null +++ b/eBook/examples/chapter_9/book/book_main/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "book/pack1" +) + +func main() { + var test1 string + test1 = pack1.ReturnStr() + fmt.Printf("ReturnStr from package1: %s\n", test1) + fmt.Printf("Integer from package1: %d\n", pack1.Pack1Int) + //fmt.Printf("Float from package1: %f\n", pack1.pack1Float) +} diff --git a/eBook/examples/chapter_9/book/pack1/pack1.go b/eBook/examples/chapter_9/book/pack1/pack1.go new file mode 100644 index 0000000..c4036ac --- /dev/null +++ b/eBook/examples/chapter_9/book/pack1/pack1.go @@ -0,0 +1,8 @@ +package pack1 + +var Pack1Int int = 42 +var pack1Float = 3.14 + +func ReturnStr() string { + return "Hello main!" +} \ No newline at end of file diff --git a/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language.html b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language.html new file mode 100644 index 0000000..31455a5 --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language.html @@ -0,0 +1,152 @@ + + + + Package sort - The Go Programming Language + + + + + +
    +
    +

    The Go Programming Language

    + + +
    +
    + + +

    Package sort

    + + + + + + + + +

    import "doc_example"

    +

    +Sorting using a general interface: +

    + +

    +

    Package files

    + + sort.go + +

    +

    func Float64sAreSorted

    +

    func Float64sAreSorted(a []float64) bool

    + +

    func IntsAreSorted

    +

    func IntsAreSorted(a []int) bool

    + +

    func IsSorted

    +

    func IsSorted(data Interface) bool

    +

    +Test if data is sorted +

    + +

    func Sort

    +

    func Sort(data Interface)

    +

    +General sort function +

    + +

    func SortFloat64s

    +

    func SortFloat64s(a []float64)

    + +

    func SortInts

    +

    func SortInts(a []int)

    +

    +Convenience wrappers for common cases +

    + +

    func SortStrings

    +

    func SortStrings(a []string)

    + +

    func StringsAreSorted

    +

    func StringsAreSorted(a []string) bool

    + +

    type Float64Array

    + +

    type Float64Array []float64

    +

    func (Float64Array) Len

    +

    func (p Float64Array) Len() int

    + +

    func (Float64Array) Less

    +

    func (p Float64Array) Less(i, j int) bool

    + +

    func (Float64Array) Swap

    +

    func (p Float64Array) Swap(i, j int)

    + +

    type IntArray

    +

    +Convenience types for common cases: IntArray +

    + +

    type IntArray []int

    +

    func (IntArray) Len

    +

    func (p IntArray) Len() int

    + +

    func (IntArray) Less

    +

    func (p IntArray) Less(i, j int) bool

    + +

    func (IntArray) Swap

    +

    func (p IntArray) Swap(i, j int)

    + +

    type Interface

    +

    +Sorting interface +

    + +

    type Interface interface {
    +    Len() int
    +    Less(i, j int) bool
    +    Swap(i, j int)
    +}

    +

    type StringArray

    + +

    type StringArray []string

    +

    func (StringArray) Len

    +

    func (p StringArray) Len() int

    + +

    func (StringArray) Less

    +

    func (p StringArray) Less(i, j int) bool

    + +

    func (StringArray) Swap

    +

    func (p StringArray) Swap(i, j int)

    + +

    Other packages

    +

    + main
    +

    + +
    +
    +

    Build version release.r58 8731. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.

    +
    +
    + + + \ No newline at end of file diff --git a/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/all.css b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/all.css new file mode 100644 index 0000000..a985d8f --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/all.css @@ -0,0 +1,205 @@ +/* General Styles */ +body { + font-family: "Bitstream Vera Sans", Verdana, sans-serif; + font-size: 81.25%; + line-height: 1.23em; + padding: 0; + margin: 1.23em; + background: white; + color: black; +} +a { + color: #04a; + text-decoration: none; +} +a:visited { + color: #04a; +} +a:hover { + color: #a40; + text-decoration: underline; +} +a:active { + color: #c00; +} +code, pre { + font-size: 1.2em; +} +pre { + background: #F0F0F0; + padding: 0.5em 1em; +} + +/* Top bar */ +#container { + width: 100%; + margin: auto; +} +#topnav { + height: 55px; + background: url(/doc/logo.png) no-repeat top left; +} +a#logo-box { + display: block; + height: 55px; +} +h1#title { + display: none; +} +#nav-main { + float: right; + width: 500px; + margin-top: -5px; + text-align: center; +} +#nav-main ul { + padding-left: 0; + margin-left: 0; + margin-bottom: 0.5em; +} +#nav-main li a { + display: inline; + display: inline-block; + padding: .46em .62em .38em .62em; +} +#nav-main li a:link, +#nav-main li a:visited { + color: #000; +} +#nav-main li { + display: inline; + display: inline-block; + background: #e6e6e6 url(/doc/button_background.png) repeat-x; + border: solid 1px #999; + margin-left: -1px; + text-shadow: #fff 0 1px 0; + box-shadow: 0 1px 1px #ccc; + -moz-box-shadow: 0 1px 1px #ccc; + -webkit-box-shadow: 0 1px 1px #ccc; +} +#nav-main li:first-child { + -moz-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; +} +#nav-main li:last-child { + -moz-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} +#nav-main .quickref { + color: #444; +} +#nav-main .quickref .sep { + color: #999; +} +#search { + width: 120px; + margin-left: 0.5em; +} +#search.inactive { + text-align: center; + color: #444; +} + +/* Footer */ +#site-info { + position: relative; + text-align: center; +} +#site-info, #site-info a:link, #site-info a:visited { + color: #aaa; +} + +/* Content */ +#content { + clear: both; + padding: 0; + position: relative; + margin-top: 1.5em; + margin-bottom: 1.5em; + border-top: solid 1px #aaa; + border-bottom: solid 1px #aaa; +} +.left-column { + width: 49%; + float: left; +} +.right-column { + width: 49%; + float: right; +} +.end-columns { + clear: both; +} +#content h1 { + margin-bottom: -0em; + padding: 0; +} +#content h2 { + border-top: 2px solid #ddd; + padding: 8px 0; + margin: 1.5em 0 0; +} +#content .subtitle { + margin-top: 1em; + display: block; +} +.navtop a { + font-weight: normal; font-size: 7pt; + float: right; color: #999; +} + +/* Content and Code Highlighting */ +pre.ebnf, pre.grammar { + background: #FFFFE0; +} +span.ln { + font-size: 80%; + color: #777777; +} +span.comment { + color: #002090; +} +span.highlight { + background: #FF9900; + font-weight: bold; +} +span.highlight-comment { + background: #FF9900; + font-weight: bold; + color: #002090; +} +span.selection { + background: #FFFF00 +} +span.selection-comment { + color: #002090; + background: #FFFF00 +} +span.selection-highlight { + background: #FF9900; + font-weight: bold; +} +span.selection-highlight-comment { + background: #FF9900; + font-weight: bold; + color: #002090; +} +span.alert { + color: #D00000; +} +#nav table { + width: 100%; +} +.detail { + padding: 0.25em 1em; + background: #F4F4F4; +} +sup.new { + color: red; + font-size: 8px; + line-height: 0; +} diff --git a/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/godocs.js b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/godocs.js new file mode 100644 index 0000000..946c4c3 --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/Package sort - The Go Programming Language_files/godocs.js @@ -0,0 +1,190 @@ +// Except as noted, this content is licensed under Creative Commons +// Attribution 3.0 + +/* A little code to ease navigation of these documents. + * + * On window load we: + * + Generate a table of contents (godocs_generateTOC) + * + Add links up to the top of the doc from each section (godocs_addTopLinks) + */ + +/* We want to do some stuff on page load (after the HTML is rendered). + So listen for that: + */ +function bindEvent(el, e, fn) { + if (el.addEventListener){ + el.addEventListener(e, fn, false); + } else if (el.attachEvent){ + el.attachEvent('on'+e, fn); + } +} +bindEvent(window, 'load', godocs_onload); + +function godocs_onload() { + godocs_bindSearchEvents(); + godocs_generateTOC(); + godocs_addTopLinks(); +} + +function godocs_bindSearchEvents() { + var search = document.getElementById('search'); + if (!search) { + // no search box (index disabled) + return; + } + function clearInactive() { + if (search.className == "inactive") { + search.value = ""; + search.className = ""; + } + } + function restoreInactive() { + if (search.value != "") { + return; + } + if (search.type != "search") { + search.value = search.getAttribute("placeholder"); + } + search.className = "inactive"; + } + restoreInactive(); + bindEvent(search, 'focus', clearInactive); + bindEvent(search, 'blur', restoreInactive); +} + +/* Generates a table of contents: looks for h2 and h3 elements and generates + * links. "Decorates" the element with id=="nav" with this table of contents. + */ +function godocs_generateTOC() { + var navbar = document.getElementById('nav'); + if (!navbar) { return; } + + var toc_items = []; + + var i; + for (i = 0; i < navbar.parentNode.childNodes.length; i++) { + var node = navbar.parentNode.childNodes[i]; + if ((node.tagName == 'h2') || (node.tagName == 'H2')) { + if (!node.id) { + node.id = 'tmp_' + i; + } + var text = godocs_nodeToText(node); + if (!text) { continue; } + + var textNode = document.createTextNode(text); + + var link = document.createElement('a'); + link.href = '#' + node.id; + link.appendChild(textNode); + + // Then create the item itself + var item = document.createElement('dt'); + + item.appendChild(link); + toc_items.push(item); + } + if ((node.tagName == 'h3') || (node.tagName == 'H3')) { + if (!node.id) { + node.id = 'tmp_' + i; + } + var text = godocs_nodeToText(node); + if (!text) { continue; } + + var textNode = document.createTextNode(text); + + var link = document.createElement('a'); + link.href = '#' + node.id; + link.appendChild(textNode); + + // Then create the item itself + var item = document.createElement('dd'); + + item.appendChild(link); + toc_items.push(item); + } + } + + if (toc_items.length <= 1) { return; } + + var dl1 = document.createElement('dl'); + var dl2 = document.createElement('dl'); + + var split_index = (toc_items.length / 2) + 1; + if (split_index < 8) { + split_index = toc_items.length; + } + + for (i = 0; i < split_index; i++) { + dl1.appendChild(toc_items[i]); + } + for (/* keep using i */; i < toc_items.length; i++) { + dl2.appendChild(toc_items[i]); + } + + var tocTable = document.createElement('table'); + navbar.appendChild(tocTable); + tocTable.className = 'unruled'; + var tocBody = document.createElement('tbody'); + tocTable.appendChild(tocBody); + + var tocRow = document.createElement('tr'); + tocBody.appendChild(tocRow); + + // 1st column + var tocCell = document.createElement('td'); + tocCell.className = 'first'; + tocRow.appendChild(tocCell); + tocCell.appendChild(dl1); + + // 2nd column + tocCell = document.createElement('td'); + tocRow.appendChild(tocCell); + tocCell.appendChild(dl2); +} + +/* Returns the "This sweet header" from

    This sweet header

    . + * Takes a node, returns a string. + */ +function godocs_nodeToText(node) { + var TEXT_NODE = 3; // Defined in Mozilla but not MSIE :( + + var text = ''; + for (var j = 0; j != node.childNodes.length; j++) { + var child = node.childNodes[j]; + if (child.nodeType == TEXT_NODE) { + if (child.nodeValue != '[Top]') { //ok, that's a hack, but it works. + text = text + child.nodeValue; + } + } else { + text = text + godocs_nodeToText(child); + } + } + return text; +} + +/* For each H2 heading, add a link up to the #top of the document. + * (As part of this: ensure existence of 'top' named anchor link + * (theoretically at doc's top).) + */ +function godocs_addTopLinks() { + /* Make sure there's a "top" to link to. */ + var top = document.getElementById('top'); + if (!top) { + document.body.id = 'top'; + } + + if (!document.getElementsByTagName) return; // no browser support + + var headers = document.getElementsByTagName('h2'); + + for (var i = 0; i < headers.length; i++) { + var span = document.createElement('span'); + span.className = 'navtop'; + var link = document.createElement('a'); + span.appendChild(link); + link.href = '#top'; + var textNode = document.createTextNode('[Top]'); + link.appendChild(textNode); + headers[i].appendChild(span); + } +} diff --git a/eBook/examples/chapter_9/doc_example/sort.go b/eBook/examples/chapter_9/doc_example/sort.go new file mode 100644 index 0000000..bced106 --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/sort.go @@ -0,0 +1,59 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Sorting using a general interface +package sort + +// Sorting interface +type Interface interface { + Len() int + Less(i, j int) bool + Swap(i, j int) +} + +// General sort function +func Sort(data Interface) { + for i := 1; i < data.Len(); i++ { + for j := i; j > 0 && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} + +// Test if data is sorted +func IsSorted(data Interface) bool { + n := data.Len() + for i := n - 1; i > 0; i-- { + if data.Less(i, i-1) { + return false + } + } + return true +} + +// Convenience types for common cases: IntArray +type IntArray []int + +func (p IntArray) Len() int { return len(p) } +func (p IntArray) Less(i, j int) bool { return p[i] < p[j] } +func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type Float64Array []float64 +func (p Float64Array) Len() int { return len(p) } +func (p Float64Array) Less(i, j int) bool { return p[i] < p[j] } +func (p Float64Array) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type StringArray []string +func (p StringArray) Len() int { return len(p) } +func (p StringArray) Less(i, j int) bool { return p[i] < p[j] } +func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// Convenience wrappers for common cases +func SortInts(a []int) { Sort(IntArray(a)) } +func SortFloat64s(a []float64) { Sort(Float64Array(a)) } +func SortStrings(a []string) { Sort(StringArray(a)) } + +func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) } +func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Array(a)) } +func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) } \ No newline at end of file diff --git a/eBook/examples/chapter_9/doc_example/sortmain.go b/eBook/examples/chapter_9/doc_example/sortmain.go new file mode 100644 index 0000000..da63508 --- /dev/null +++ b/eBook/examples/chapter_9/doc_example/sortmain.go @@ -0,0 +1,82 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package gives an example of how to use a custom package with interfaces +package main + +import ( + "fmt" + "./sort" +) + +// sorting of slice of integers +func ints() { + data := []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586} + a := sort.IntArray(data) //conversion to type IntArray + sort.Sort(a) + if !sort.IsSorted(a) { + panic("fail") + } + fmt.Printf("The sorted array is: %v\n", a) +} + +// sorting of slice of strings +func strings() { + data := []string{"monday", "friday", "tuesday", "wednesday", "sunday","thursday", "", "saturday"} + a := sort.StringArray(data) + sort.Sort(a) + if !sort.IsSorted(a) { + panic("fail") + } + fmt.Printf("The sorted array is: %v\n", a) +} + +// a type which describes a day of the week +type day struct { + num int + shortName string + longName string +} + +type dayArray struct { + data []*day +} + +func (p *dayArray) Len() int { return len(p.data) } +func (p *dayArray) Less(i, j int) bool { return p.data[i].num < p.data[j].num } +func (p *dayArray) Swap(i, j int) { p.data[i], p.data[j] = p.data[j], p.data[i] } + +// sorting of custom type day +func days() { + Sunday := day{0, "SUN", "Sunday"} + Monday := day{1, "MON", "Monday"} + Tuesday := day{2, "TUE", "Tuesday"} + Wednesday := day{3, "WED", "Wednesday"} + Thursday := day{4, "THU", "Thursday"} + Friday := day{5, "FRI", "Friday"} + Saturday := day{6, "SAT", "Saturday"} + data := []*day{&Tuesday, &Thursday, &Wednesday, &Sunday, &Monday, &Friday, &Saturday} + a := dayArray{data} + sort.Sort(&a) + if !sort.IsSorted(&a) { + panic("fail") + } + for _, d := range data { + fmt.Printf("%s ", d.longName) + } + fmt.Printf("\n") +} + + +func main() { + ints() + strings() + days() +} + +/* Output: +The sorted array is: [-5467984 -784 0 0 42 59 74 238 905 959 7586 7586 9845] +The sorted array is: [ friday monday saturday sunday thursday tuesday wednesday] +Sunday Monday Tuesday Wednesday Thursday Friday Saturday +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_9/pattern.go b/eBook/examples/chapter_9/pattern.go new file mode 100644 index 0000000..a232392 --- /dev/null +++ b/eBook/examples/chapter_9/pattern.go @@ -0,0 +1,35 @@ +// pattern.go +package main + +import ( + "fmt" + "regexp" + "strconv" +) + +func main() { + searchIn := "John: 2578.34 William: 4567.23 Steve: 5632.18" // string to search + pat := "[0-9]+.[0-9]+" // pattern search for in searchIn + + f := func (s string) string { + v, _ := strconv.ParseFloat(s, 32) + return strconv.FormatFloat(v * 2, 'f', 2, 32) + } + + if ok, _ := regexp.Match(pat, []byte(searchIn)); ok { + fmt.Println("Match found!") + } + + re, _ := regexp.Compile(pat) + str := re.ReplaceAllString(searchIn, "##.#") // replace pat with "##.#" + fmt.Println(str) + // using a function : + str2 := re.ReplaceAllStringFunc(searchIn, f) + fmt.Println(str2) + +} +/* Output: +Match found! +John: ##.# William: ##.# Steve: ##.# +John: 5156.68 William: 9134.46 Steve: 11264.36 +*/ \ No newline at end of file diff --git a/eBook/examples/chapter_9/reboot.go b/eBook/examples/chapter_9/reboot.go new file mode 100644 index 0000000..7250e06 --- /dev/null +++ b/eBook/examples/chapter_9/reboot.go @@ -0,0 +1,21 @@ +// reboot.go +// compile errors (Windows): +//undefined: syscall.SYS_REBOOT +// reboot.go:13: not enough arguments in call to syscall.Syscall +// Linux: compileert, uitvoeren met sudo ./6.out --> systeem herstart +package main + +import ( + "syscall" +) + +const LINUX_REBOOT_MAGIC1 uintptr = 0xfee1dead +const LINUX_REBOOT_MAGIC2 uintptr = 672274793 +const LINUX_REBOOT_CMD_RESTART uintptr = 0x1234567 + +func main() { + syscall.Syscall(syscall.SYS_REBOOT, + LINUX_REBOOT_MAGIC1, + LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART) +} diff --git a/eBook/examples/chapter_9/uppercase/uc/uc.go b/eBook/examples/chapter_9/uppercase/uc/uc.go new file mode 100644 index 0000000..221c5ab --- /dev/null +++ b/eBook/examples/chapter_9/uppercase/uc/uc.go @@ -0,0 +1,8 @@ +// uc.go +package uc + +import "strings" + +func UpperCase(str string) string { + return strings.ToUpper(str) +} diff --git a/eBook/examples/chapter_9/uppercase/uc/uc_test.go b/eBook/examples/chapter_9/uppercase/uc/uc_test.go new file mode 100644 index 0000000..3d01c71 --- /dev/null +++ b/eBook/examples/chapter_9/uppercase/uc/uc_test.go @@ -0,0 +1,23 @@ +// uc_test.go +package uc + +import "testing" + +type ucTest struct { + in, out string +} + +var ucTests = []ucTest { + ucTest{"abc", "ABC"}, + ucTest{"cvo-az", "CVO-AZ"}, + ucTest{"Antwerp", "ANTWERP"}, +} + +func TestUC(t *testing.T) { + for _, ut := range ucTests { + uc := UpperCase(ut.in) + if uc != ut.out { + t.Errorf("UpperCase(%s) = %s, must be %s.", ut.in, uc, ut.out) + } + } +} diff --git a/eBook/examples/chapter_9/uppercase/uc_main/ucmain.go b/eBook/examples/chapter_9/uppercase/uc_main/ucmain.go new file mode 100644 index 0000000..a415f2f --- /dev/null +++ b/eBook/examples/chapter_9/uppercase/uc_main/ucmain.go @@ -0,0 +1,12 @@ +// main.go +package main + +import ( + "fmt" + "uppercase/uc" +) + +func main() { + str1 := "USING package uc!" + fmt.Println(uc.UpperCase(str1)) +} diff --git a/eBook/examples/chapter_9/use_urlshortener.go b/eBook/examples/chapter_9/use_urlshortener.go new file mode 100644 index 0000000..eede5e1 --- /dev/null +++ b/eBook/examples/chapter_9/use_urlshortener.go @@ -0,0 +1,55 @@ +// use_urlshortener.go +package main + +import ( + "fmt" + "net/http" + "text/template" + urlshortener "code.google.com/p/google-api-go-client/urlshortener/v1" +) + +func main() { + http.HandleFunc("/", root) + http.HandleFunc("/short", short) + http.HandleFunc("/long", long) + http.ListenAndServe("localhost:8080", nil) +} + +// the template used to show the forms and the results web page to the user +var rootHtmlTmpl = template.Must(template.New("rootHtml").Parse(` + +

    URL SHORTENER

    +{{if .}}{{.}}

    {{end}} +
    +Shorten this: + +
    +
    +
    +Expand this: http://goo.gl/ + +
    + +`)) + +func root(w http.ResponseWriter, r *http.Request) { + rootHtmlTmpl.Execute(w, nil) +} + +func short(w http.ResponseWriter, r *http.Request) { + longUrl := r.FormValue("longUrl") + urlshortenerSvc, _ := urlshortener.New(http.DefaultClient) + url, _ := urlshortenerSvc.Url.Insert(&urlshortener.Url{LongUrl: longUrl,}).Do() + rootHtmlTmpl.Execute(w, fmt.Sprintf("Shortened version of %s is : %s", longUrl, url.Id)) +} + +func long(w http.ResponseWriter, r *http.Request) { + shortUrl := "http://goo.gl/" + r.FormValue("shortUrl") + urlshortenerSvc, _ := urlshortener.New(http.DefaultClient) + url, err := urlshortenerSvc.Url.Get(shortUrl).Do() + if err != nil { + fmt.Println("error: %v", err) + return + } + rootHtmlTmpl.Execute(w, fmt.Sprintf("Longer version of %s is : %s", shortUrl, url.LongUrl)) +} \ No newline at end of file diff --git a/eBook/exercises/chapter_10/anonymous_struct.go b/eBook/exercises/chapter_10/anonymous_struct.go new file mode 100755 index 0000000..57f281c --- /dev/null +++ b/eBook/exercises/chapter_10/anonymous_struct.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +type C struct { +x float32; +int; +string; +} + +func main() { + c := C{3.14, 7, "hello"} + fmt.Println(c.x, c.int, c.string) // output: 3.14 7 hello + fmt.Println(c) // output: {3.14 7 hello} +} \ No newline at end of file diff --git a/eBook/exercises/chapter_10/celsius.go b/eBook/exercises/chapter_10/celsius.go new file mode 100755 index 0000000..64ae03c --- /dev/null +++ b/eBook/exercises/chapter_10/celsius.go @@ -0,0 +1,19 @@ +// celsius.go +package main + +import ( + "fmt" + "strconv" +) + +type Celsius float64 + +func (c Celsius) String() string { + return "The temperature is: " + strconv.FormatFloat(float64(c),'f', 1, 32) + " °C" +} + +func main() { + var c Celsius = 18.36 + fmt.Println(c) +} +// The temperature is: 18.4 °C diff --git a/eBook/exercises/chapter_10/days.go b/eBook/exercises/chapter_10/days.go new file mode 100755 index 0000000..8b606fc --- /dev/null +++ b/eBook/exercises/chapter_10/days.go @@ -0,0 +1,36 @@ +package main + +import "fmt" + +type Day int + +const ( + MO Day = iota + TU + WE + TH + FR + SA + SU +) + +var dayName = []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"} + +func (day Day) String() string { + return dayName[day] +} + +func main() { + var th Day = 3 + fmt.Printf("The 3rd day is: %s\n", th) + // If index > 6: panic: runtime error: index out of range + // but use the enumerated type to work with valid values: + var day = SU; + fmt.Println(day); // prints Sunday + fmt.Println(0, MO, 1, TU) +} +/* Output: +The 3rd day is: Thursday +Sunday +0 Monday 1 Tuesday +*/ diff --git a/eBook/exercises/chapter_10/employee_salary.go b/eBook/exercises/chapter_10/employee_salary.go new file mode 100755 index 0000000..af1713b --- /dev/null +++ b/eBook/exercises/chapter_10/employee_salary.go @@ -0,0 +1,25 @@ +// methods1.go +package main + +import "fmt" + +/* basic data structure upon with we'll define methods */ +type employee struct { + salary float32 +} + +/* a method which will add a specified percent to an + employees salary */ +func (this *employee) giveRaise(pct float32) { + this.salary += this.salary * pct +} + +func main() { + /* create an employee instance */ + var e = new(employee) + e.salary = 100000; + /* call our method */ + e.giveRaise(0.04) + fmt.Printf("Employee now makes %f", e.salary) +} +// Employee now makes 104000.000000 \ No newline at end of file diff --git a/eBook/exercises/chapter_10/inherit_methods.go b/eBook/exercises/chapter_10/inherit_methods.go new file mode 100755 index 0000000..256fbff --- /dev/null +++ b/eBook/exercises/chapter_10/inherit_methods.go @@ -0,0 +1,40 @@ +package main + +import "fmt" + +type Base struct { + id string +} + +func (b *Base) Id() string { + return b.id +} + +func (b *Base) SetId(id string) { + b.id = id +} + +type Person struct { + Base + FirstName string + LastName string +} + +type Employee struct { + Person + salary float32 +} + +func main() { + idjb := Base{"007"} + jb := Person{idjb, "James", "Bond"} + e := &Employee{jb, 100000.} + fmt.Printf("ID of our hero: %v\n", e.Id()) + // Change the id: + e.SetId("007B") + fmt.Printf("The new ID of our hero: %v\n", e.Id()) +} +/* Output: +ID of our hero: 007 +The new ID of our hero: 007B +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/inheritance_car.go b/eBook/exercises/chapter_10/inheritance_car.go new file mode 100755 index 0000000..1858aac --- /dev/null +++ b/eBook/exercises/chapter_10/inheritance_car.go @@ -0,0 +1,59 @@ +// inheritance_car.go +package main + +import ( + "fmt" +) + +type Engine interface { + Start() + Stop() +} + +type Car struct { + wheelCount int + Engine +} + +// define a behavior for Car +func (car Car) numberOfWheels() int { + return car.wheelCount +} + +type Mercedes struct { + Car //anonymous field Car +} + +// a behavior only available for the Mercedes +func (m *Mercedes) sayHiToMerkel() { + fmt.Println("Hi Angela!") +} + +func (c *Car) Start() { + fmt.Println("Car is started") +} + +func (c *Car) Stop() { + fmt.Println("Car is stopped") +} + +func (c *Car) GoToWorkIn() { + // get in car + c.Start(); + // drive to work + c.Stop(); + // get out of car +} + +func main() { + m := Mercedes{Car{4, nil}} + fmt.Println("A Mercedes has this many wheels: ", m.numberOfWheels()) + m.GoToWorkIn() + m.sayHiToMerkel() +} +/* Output: +A Mercedes has this many wheels: 4 +Car is started +Car is stopped +Hi Angela! +*/ diff --git a/eBook/exercises/chapter_10/iteration_list.go b/eBook/exercises/chapter_10/iteration_list.go new file mode 100755 index 0000000..75b6f58 --- /dev/null +++ b/eBook/exercises/chapter_10/iteration_list.go @@ -0,0 +1,23 @@ +/* +iteration_list.go:12: cannot define new methods on non-local type list.List +iteration_list.go:17: lst.Iter undefined (type *list.List has no field or method Iter) +---- Build file exited with code 1 +*/ +package main + +import "container/list" + +// cannot define new methods on non-local type list.List +// List iterator: +func (p *list.List) Iter() { +} + +func main() { + lst := new(list.List) + for _ = range lst.Iter() { + } +} + + + + diff --git a/eBook/exercises/chapter_10/magic.go b/eBook/exercises/chapter_10/magic.go new file mode 100755 index 0000000..2cd7d1a --- /dev/null +++ b/eBook/exercises/chapter_10/magic.go @@ -0,0 +1,29 @@ +// magic.go +package main + +import "fmt" + +type Base struct{} + +func (Base) Magic() { fmt.Print("base magic ") } + +func (self Base) MoreMagic() { + self.Magic() + self.Magic() +} + +type Voodoo struct { + Base +} + +func (Voodoo) Magic() { fmt.Println("voodoo magic") } + +func main() { + v := new(Voodoo) + v.Magic() + v.MoreMagic() +} +/* Output: +voodoo magic +base magic base magic +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/main_stack.go b/eBook/exercises/chapter_10/main_stack.go new file mode 100755 index 0000000..2125005 --- /dev/null +++ b/eBook/exercises/chapter_10/main_stack.go @@ -0,0 +1,45 @@ +// Q15.go +package main + +import ( + "fmt" + "./stack/stack" +) + +func main() { + st1 := new(stack.Stack) + fmt.Printf("%v\n", st1) + st1.Push(3) + fmt.Printf("%v\n", st1) + st1.Push(7) + fmt.Printf("%v\n", st1) + st1.Push(10) + fmt.Printf("%v\n", st1) + st1.Push(99) + fmt.Printf("%v\n", st1) + p := st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) +} +/* Output: +[0:3] +[0:3] [1:7] +[0:3] [1:7] [2:10] +[0:3] [1:7] [2:10] [3:99] +Popped 99 +[0:3] [1:7] [2:10] +Popped 10 +[0:3] [1:7] +Popped 7 +[0:3] +Popped 3 +*/ diff --git a/eBook/exercises/chapter_10/personex1.go b/eBook/exercises/chapter_10/personex1.go new file mode 100755 index 0000000..df4e7ae --- /dev/null +++ b/eBook/exercises/chapter_10/personex1.go @@ -0,0 +1,40 @@ +package main + +import ( + "fmt" + "strings" +) + +type Person struct { + firstName string + lastName string +} + +func upPerson (p Person) { + p.firstName = strings.ToUpper(p.firstName) + p.lastName = strings.ToUpper(p.lastName) +} + +func main() { +// 1- struct as a value type: + var pers1 Person + pers1.firstName = "Chris" + pers1.lastName = "Woodward" + upPerson(pers1) + fmt.Printf("The name of the person is %s %s\n", pers1.firstName, pers1.lastName) +// 2 - struct as a pointer: + pers2 := new(Person) + pers2.firstName = "Chris" + pers2.lastName = "Woodward" + upPerson(*pers2) + fmt.Printf("The name of the person is %s %s\n", pers2.firstName, pers2.lastName) +// 3 - struct as a literal: + pers3 := &Person{"Chris","Woodward"} + upPerson(*pers3) + fmt.Printf("The name of the person is %s %s\n", pers3.firstName, pers3.lastName) +} +/* Output: +The name of the person is Chris Woodward +The name of the person is Chris Woodward +The name of the person is Chris Woodward +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/point.go b/eBook/exercises/chapter_10/point.go new file mode 100755 index 0000000..a536cbe --- /dev/null +++ b/eBook/exercises/chapter_10/point.go @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" + "math" +) + +type Point struct { + X, Y float64 +} + +type Point3 struct { + X, Y, Z float64 +} + +type Polar struct { + R, T float64 +} + +func Abs(p *Point) float64 { + return math.Sqrt(float64(p.X*p.X + p.Y*p.Y)) +} + +func Scale(p *Point,s float64) (q Point) { + q.X = p.X * s + q.Y = p.Y * s + return +} + +func main() { + p1 := new(Point) + p1.X = 3 + p1.Y = 4 + fmt.Printf("The length of the vector p1 is: %f\n", Abs(p1) ) + + p2:= &Point{4, 5} + fmt.Printf("The length of the vector p2 is: %f\n", Abs(p2) ) + + q := Scale(p1, 5) + fmt.Printf("The length of the vector q is: %f\n", Abs(&q) ) + fmt.Printf("Point p1 scaled by 5 has the following coordinates: X %f - Y %f", q.X, q.Y) +} +/* Output: +The length of the vector p1 is: 5.000000 +The length of the vector p2 is: 6.403124 +The length of the vector q is: 25.000000 +Point p1 scaled by 5 has the following coordinates: X 15.000000 - Y 20.000000 +*/ + diff --git a/eBook/exercises/chapter_10/point_methods.go b/eBook/exercises/chapter_10/point_methods.go new file mode 100755 index 0000000..fef05bb --- /dev/null +++ b/eBook/exercises/chapter_10/point_methods.go @@ -0,0 +1,54 @@ +// float64 is necessary as input to math.Sqrt() +package main + +import ( + "fmt" + "math" +) + +type Point struct { + X, Y float64 +} + +func (p *Point) Scale(s float64) { + p.X *= s + p.Y *= s +} + +func (p *Point) Abs() float64 { + return math.Sqrt(float64(p.X*p.X + p.Y*p.Y)) +} + +type Point3 struct { + X, Y, Z float64 +} + +func (p *Point3) Abs() float64 { + return math.Sqrt(float64(p.X*p.X + p.Y*p.Y + p.Z*p.Z)) +} + +type Polar struct { + R, T float64 +} + +func (p Polar) Abs() float64 { return p.R } + +func main() { + p1 := new(Point) + p1.X = 3 + p1.Y = 4 + fmt.Printf("The length of the vector p1 is: %f\n", p1.Abs()) + + p2:= &Point{4, 5} + fmt.Printf("The length of the vector p2 is: %f\n", p2.Abs() ) + + p1.Scale(5) + fmt.Printf("The length of the vector p1 after scaling is: %f\n", p1.Abs() ) + fmt.Printf("Point p1 after scaling has the following coordinates: X %f - Y %f", p1.X, p1.Y) +} +/* Output: +The length of the vector p1 is: 5.000000 +The length of the vector p2 is: 6.403124 +The length of the vector p1 after scaling is: 25.000000 +Point p1 after scaling has the following coordinates: X 15.000000 - Y 20.000000 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/rectangle.go b/eBook/exercises/chapter_10/rectangle.go new file mode 100755 index 0000000..7f3a4b2 --- /dev/null +++ b/eBook/exercises/chapter_10/rectangle.go @@ -0,0 +1,28 @@ +// rectangle.go +package main + +import "fmt" + +type Rectangle struct { + length, width int +} + +func (r *Rectangle) Area() int { + return r.length * r.width +} + +func (r *Rectangle) Perimeter() int { + return 2* (r.length + r.width) +} + +func main() { + r1 := Rectangle{4, 3} + fmt.Println("Rectangle is: ", r1) + fmt.Println("Rectangle area is: ", r1.Area()) + fmt.Println("Rectangle perimeter is: ", r1.Perimeter()) +} +/* Output: +Rectangle is: {4 3} +Rectangle area is: 12 +Rectangle perimeter is: 14 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_10/stack/stack_struct.go b/eBook/exercises/chapter_10/stack/stack_struct.go new file mode 100755 index 0000000..08a58e4 --- /dev/null +++ b/eBook/exercises/chapter_10/stack/stack_struct.go @@ -0,0 +1,32 @@ +// stack_struct.go +package stack + +import "strconv" +const LIMIT = 10 + +type Stack struct { + ix int // first free position, so data[ix] == 0 + data [LIMIT]int +} + +func (st *Stack) Push(n int) { + if (st.ix + 1 > LIMIT) { + return // stack is full! + } + st.data[st.ix] = n + st.ix++ +} + +func (st *Stack) Pop() int { + st.ix-- + return st.data[st.ix] +} + +func (st Stack) String() string { + str := "" + for ix:=0; ix=0; ix-- { + if v=st[ix]; v!=0 { + st[ix] = 0 + return v + } + } + return 0 +} + +func (st Stack) String() string { + str := "" + for ix, v := range st { + str += "[" + strconv.Itoa(ix) + ":" + strconv.Itoa(v) + "] " + } + return str +} \ No newline at end of file diff --git a/eBook/exercises/chapter_10/stack_struct.go b/eBook/exercises/chapter_10/stack_struct.go new file mode 100755 index 0000000..2a0ba11 --- /dev/null +++ b/eBook/exercises/chapter_10/stack_struct.go @@ -0,0 +1,59 @@ +// stack_struct.go +package main + +import ( + "fmt" + "strconv" +) + +const LIMIT = 4 +type Stack struct { + ix int // first free position, so data[ix] == 0 + data [LIMIT]int +} + +func main() { + st1 := new(Stack) + fmt.Printf("%v\n", st1) + st1.Push(3) + fmt.Printf("%v\n", st1) + st1.Push(7) + fmt.Printf("%v\n", st1) + st1.Push(10) + fmt.Printf("%v\n", st1) + st1.Push(99) + fmt.Printf("%v\n", st1) + p := st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) + p = st1.Pop() + fmt.Printf("Popped %d\n", p) + fmt.Printf("%v\n", st1) +} + +func (st *Stack) Push(n int) { + if (st.ix + 1 > LIMIT) { + return // stack is full! + } + st.data[st.ix] = n + st.ix++ +} + +func (st *Stack) Pop() int { + st.ix-- + return st.data[st.ix] +} + +func (st Stack) String() string { + str := "" + for ix:=0; ix 0; i-- { + if data.Less(i, i-1) { + return false + } + } + return true +} + +type Float64Array []float64 + +func (p Float64Array) Len() int { return len(p) } +func (p Float64Array) Less(i, j int) bool { return p[i] < p[j] } +func (p Float64Array) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func NewFloat64Array() Float64Array { + return make([]float64, 25) +} + +func (p Float64Array) Fill(n int) { + rand.Seed(int64(time.Now().Nanosecond())) + for i := 0; i < n; i++ { + p[i] = 100 * (rand.Float64()) + } +} + +func (p Float64Array) List() string { + s := "{ " + for i := 0; i < p.Len(); i++ { + if p[i] == 0 { + continue + } + s += fmt.Sprintf("%3.1f ", p[i]) + } + s += " }" + return s +} + +func (p Float64Array) String() string { + return p.List() +} diff --git a/eBook/exercises/chapter_11/float_sortmain.go b/eBook/exercises/chapter_11/float_sortmain.go new file mode 100755 index 0000000..e7b1922 --- /dev/null +++ b/eBook/exercises/chapter_11/float_sortmain.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "./float64" +) + +func main() { + f1 := float64.NewFloat64Array() + f1.Fill(10) + fmt.Printf("Before sorting %s\n", f1) + float64.Sort(f1) + fmt.Printf("After sorting %s\n", f1) + if float64.IsSorted(f1) { + fmt.Println("The float64 array is sorted!") + } else { + fmt.Println("The float64 array is NOT sorted!") + } +} + +/* Output: +Before sorting { 55.0 82.3 36.4 66.6 25.3 82.7 47.4 21.5 4.6 81.6 } +After sorting { 4.6 21.5 25.3 36.4 47.4 55.0 66.6 81.6 82.3 82.7 } +The float64 array is sorted! +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_11/interface_nil.go b/eBook/exercises/chapter_11/interface_nil.go new file mode 100755 index 0000000..b2a4d4d --- /dev/null +++ b/eBook/exercises/chapter_11/interface_nil.go @@ -0,0 +1,46 @@ +// interface_nil.go +package main + +import "fmt" + +type Any interface {} +type Anything struct {} + +func main() { + any := getAny() + if any == nil { + fmt.Println("any is nil") + } else { + fmt.Println("any is not nil") + } +/* + // to get the inner value: + anything := any.(*Anything) + if anything == nil { + fmt.Println("anything is nil") + } else { + fmt.Println("anything is not nil") + } +*/ +} + +func getAny() Any { + return getAnything() +} + +func getAnything() *Anything { + return nil +} + +/* Output: +any is not nil +WHY? +you would perhaps expect: any is nil,because getAnything() returns that +BUT: +the interface value any is storing a value, so it is not nil. +It just so happens that the particular value it is storing is a nil pointer. +The any variable has a type, so it's not a nil interface, +rather an interface variable with type Any and concrete value (*Anything)(nil). +To get the inner value of any, use: anything := any.(*Anything) +now anything contains nil ! +*/ diff --git a/eBook/exercises/chapter_11/interface_poly3.go b/eBook/exercises/chapter_11/interface_poly3.go new file mode 100755 index 0000000..f75b454 --- /dev/null +++ b/eBook/exercises/chapter_11/interface_poly3.go @@ -0,0 +1,68 @@ +// interface_poly3.go +package main + +import ( + "fmt" + "math" +) + +type Shaper interface { + Area() float32 +} + +type Shape struct {} +func (sh Shape) Area() float32 { + return -1 // the shape is indetermined, so we return something impossible +} + +type Square struct { + side float32 + Shape +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +type Rectangle struct { + length, width float32 + Shape +} + +func (r *Rectangle) Area() float32 { + return r.length * r.width +} + +type Circle struct { + radius float32 + Shape +} + +func (c *Circle) Area() float32 { + return math.Pi * c.radius * c.radius +} + +func main() { + s := Shape{} + r := &Rectangle{5, 3, s} // Area() of Rectangle needs a value + q := &Square{5, s} // Area() of Square needs a pointer + c := &Circle{2.5, s} + shapes := []Shaper{r, q, c, s} + fmt.Println("Looping through shapes for area ...") + for n, _ := range shapes { + fmt.Println("Shape details: ", shapes[n]) + fmt.Println("Area of this shape is: ", shapes[n].Area()) + } +} +/* Output: +Looping through shapes for area ... +Shape details: {5 3} +Area of this shape is: 15 +Shape details: &{5} +Area of this shape is: 25 +Shape details: &{2.5} +Area of this shape is: 19.634954 +Shape details: {} +Area of this shape is: -1 +*/ + diff --git a/eBook/exercises/chapter_11/interfaces_ext.go b/eBook/exercises/chapter_11/interfaces_ext.go new file mode 100755 index 0000000..4391ebc --- /dev/null +++ b/eBook/exercises/chapter_11/interfaces_ext.go @@ -0,0 +1,51 @@ +package main + +import "fmt" + +type Square struct { + side float32 +} + +type Triangle struct { + base float32 + height float32 +} + +type AreaInterface interface { + Area() float32 +} + +type PeriInterface interface { + Perimeter() float32 +} +func main() { + var areaIntf AreaInterface + var periIntf PeriInterface + + sq1 := new(Square) + sq1.side = 5 + tr1 := new(Triangle) + tr1.base = 3 + tr1.height = 5 + + areaIntf = sq1 + fmt.Printf("The square has area: %f\n", areaIntf.Area()) + + periIntf = sq1 + fmt.Printf("The square has perimeter: %f\n", periIntf.Perimeter()) + + areaIntf = tr1 + fmt.Printf("The triangle has area: %f\n", areaIntf.Area()) +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +func (sq *Square) Perimeter() float32 { + return 4 * sq.side +} + +func (tr *Triangle) Area() float32 { + return 0.5 * tr.base*tr.height +} diff --git a/eBook/exercises/chapter_11/interfaces_poly2.go b/eBook/exercises/chapter_11/interfaces_poly2.go new file mode 100755 index 0000000..ce7ec97 --- /dev/null +++ b/eBook/exercises/chapter_11/interfaces_poly2.go @@ -0,0 +1,57 @@ +// interfaces_poly2.go +package main + +import ( + "fmt" + "math" +) + +type Shaper interface { + Area() float32 +} + +type Square struct { + side float32 +} + +func (sq *Square) Area() float32 { + return sq.side * sq.side +} + +type Rectangle struct { + length, width float32 +} + +func (r Rectangle) Area() float32 { + return r.length * r.width +} + +type Circle struct { + radius float32 +} + +func (c *Circle) Area() float32 { + return math.Pi * c.radius * c.radius +} + +func main() { + r := Rectangle{5, 3} // Area() of Rectangle needs a value + q := &Square{5} // Area() of Square needs a pointer + c := &Circle{2.5} + fmt.Println("Looping through shapes for area ...") + // shapes := []Shaper{Shaper(r), Shaper(q), Shaper(c)} + shapes := []Shaper{r, q, c} + for n, _ := range shapes { + fmt.Println("Shape details: ", shapes[n]) + fmt.Println("Area of this shape is: ", shapes[n].Area()) + } +} +/* Output: +Looping through shapes for area ... +Shape details: {5 3} +Area of this shape is: 15 +Shape details: &{5} +Area of this shape is: 25 +Shape details: &{2.5} +Area of this shape is: 19.634954 +*/ diff --git a/eBook/exercises/chapter_11/main_stack.go b/eBook/exercises/chapter_11/main_stack.go new file mode 100755 index 0000000..1404db1 --- /dev/null +++ b/eBook/exercises/chapter_11/main_stack.go @@ -0,0 +1,29 @@ +// main_stack.go +package main + +import ( + "fmt" + "./stack/stack" +) + +var st1 stack.Stack + +func main() { + st1.Push("Brown") + st1.Push(3.14) + st1.Push(100) + st1.Push([]string{"Java", "C++", "Python", "C#", "Ruby"}) + for { + item, err := st1.Pop() + if err != nil { + break + } + fmt.Println(item) + } +} +/* Output: +[Java C++ Python C# Ruby] +100 +3.14 +Brown +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_11/main_stack_v2.go b/eBook/exercises/chapter_11/main_stack_v2.go new file mode 100755 index 0000000..447374a --- /dev/null +++ b/eBook/exercises/chapter_11/main_stack_v2.go @@ -0,0 +1,17 @@ +// main_stack_v2.go +package main + +import ( + "./stack/collection" + "fmt" +) + +func main() { + var s collection.Stack + s.Push("world") + s.Push("hello, ") + for s.Size() > 0 { + fmt.Print(s.Pop()) + } + fmt.Println() +} \ No newline at end of file diff --git a/eBook/exercises/chapter_11/map_function_interface.go b/eBook/exercises/chapter_11/map_function_interface.go new file mode 100755 index 0000000..90edce9 --- /dev/null +++ b/eBook/exercises/chapter_11/map_function_interface.go @@ -0,0 +1,62 @@ +package main + +import "fmt" + +type obj interface{} + +func main() { + // define a generic lambda function mf: + mf := func(i obj) obj { + switch i.(type) { + case int: + return i.(int) * 2 + case string: + return i.(string) + i.(string) + } + return i + } + + isl := []obj{0, 1, 2, 3, 4, 5} + res1 := mapFunc(mf, isl) + for _, v := range res1 { + fmt.Println(v) + } + println() + + ssl := []obj{"0", "1", "2", "3", "4", "5"} + res2 := mapFunc(mf, ssl) + for _, v := range res2 { + fmt.Println(v) + } +} + +func mapFunc(mf func(obj) obj, list []obj) ([]obj) { + result := make([]obj, len(list)) + + for ix, v := range list { + result[ix] = mf(v) + } + + // Equivalent: + /* + for ix := 0; ix 0 {os.Stdout.WriteString(" ")} + switch a := arg.(type) { // type switch + case Stringer: os.Stdout.WriteString(a.String()) + case int: os.Stdout.WriteString(strconv.Itoa(a)) + case string: os.Stdout.WriteString(a) + // more types + default: os.Stdout.WriteString("???") + } + } +} + +func main() { + print(Day(1), "was", Celsius(18.36)) // Tuesday was 18.4 °C +} +// Tuesday was 18.4 °C \ No newline at end of file diff --git a/eBook/exercises/chapter_11/simple_interface.go b/eBook/exercises/chapter_11/simple_interface.go new file mode 100755 index 0000000..f4a6fd9 --- /dev/null +++ b/eBook/exercises/chapter_11/simple_interface.go @@ -0,0 +1,34 @@ +// simple_interface.go +package main + +import ( + "fmt" +) + +type Simpler interface { + Get() int + Put(int) +} + +type Simple struct { + i int +} + +func (p *Simple) Get() int { + return p.i +} + +func (p *Simple) Put(u int) { + p.i = u +} + +func fI(it Simpler) int { + it.Put(5) + return it.Get() +} + +func main() { + var s Simple + fmt.Println(fI(&s)) // &s is required because Get() is defined with a receiver type pointer +} +// Output: 5 \ No newline at end of file diff --git a/eBook/exercises/chapter_11/simple_interface2.go b/eBook/exercises/chapter_11/simple_interface2.go new file mode 100755 index 0000000..5fb495b --- /dev/null +++ b/eBook/exercises/chapter_11/simple_interface2.go @@ -0,0 +1,61 @@ +// simple_interface2.go +package main + +import ( + "fmt" +) + +type Simpler interface { + Get() int + Set(int) +} + +type Simple struct { + i int +} + +func (p *Simple) Get() int { + return p.i +} + +func (p *Simple) Set(u int) { + p.i = u +} + +type RSimple struct { + i int + j int +} + +func (p *RSimple) Get() int { + return p.j +} + +func (p *RSimple) Set(u int) { + p.j = u +} + +func fI(it Simpler) int { + switch it.(type) { + case *Simple: + it.Set(5) + return it.Get() + case *RSimple: + it.Set(50) + return it.Get() + default: + return 99 + } + return 0 +} + +func main() { + var s Simple + fmt.Println(fI(&s)) // &s is required because Get() is defined with a receiver type pointer + var r RSimple + fmt.Println(fI(&r)) +} +/* Output: +5 +50 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_11/simple_interface3.go b/eBook/exercises/chapter_11/simple_interface3.go new file mode 100755 index 0000000..f747f4b --- /dev/null +++ b/eBook/exercises/chapter_11/simple_interface3.go @@ -0,0 +1,74 @@ +// simple_interface2.go +package main + +import ( + "fmt" +) + +type Simpler interface { + Get() int + Set(int) +} + +type Simple struct { + i int +} + +func (p *Simple) Get() int { + return p.i +} + +func (p *Simple) Set(u int) { + p.i = u +} + +type RSimple struct { + i int + j int +} + +func (p *RSimple) Get() int { + return p.j +} + +func (p *RSimple) Set(u int) { + p.j = u +} + +func fI(it Simpler) int { + switch it.(type) { + case *Simple: + it.Set(5) + return it.Get() + case *RSimple: + it.Set(50) + return it.Get() + default: + return 99 + } + return 0 +} + + +func gI(any interface{}) int { + // return any.(Simpler).Get() // unsafe, runtime panic possible + if v, ok := any.(Simpler); ok { + return v.Get() + } + return 0 // default value +} +/* Output: +6 +60 +*/ + +func main() { + var s Simple = Simple{6} + fmt.Println(gI(&s)) // &s is required because Get() is defined with a receiver type pointer + var r RSimple = RSimple{60,60} + fmt.Println(gI(&r)) +} +/* Output: +6 +60 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_11/sort/sort.go b/eBook/exercises/chapter_11/sort/sort.go new file mode 100755 index 0000000..9135d40 --- /dev/null +++ b/eBook/exercises/chapter_11/sort/sort.go @@ -0,0 +1,60 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package sort + +type Sorter interface { + Len() int + Less(i, j int) bool + Swap(i, j int) +} + +/* +func Sort(Sorter Interface) { + for i := 1; i < data.Len(); i++ { + for j := i; j > 0 && data.Less(j, j-1); j-- { + data.Swap(j, j-1) + } + } +} +*/ + +func Sort(data Sorter) { + for pass:=1; pass < data.Len(); pass++ { + for i:=0; i < data.Len() - pass; i++ { + if data.Less(i+1, i) { + data.Swap(i, i+1) + } + } + } +} + +func IsSorted(data Sorter) bool { + n := data.Len() + for i := n - 1; i > 0; i-- { + if data.Less(i, i-1) { + return false + } + } + return true +} + +// Convenience types for common cases +type IntArray []int + +func (p IntArray) Len() int { return len(p) } +func (p IntArray) Less(i, j int) bool { return p[i] < p[j] } +func (p IntArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +type StringArray []string + +func (p StringArray) Len() int { return len(p) } +func (p StringArray) Less(i, j int) bool { return p[i] < p[j] } +func (p StringArray) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// Convenience wrappers for common cases +func SortInts(a []int) { Sort(IntArray(a)) } +func SortStrings(a []string) { Sort(StringArray(a)) } + +func IntsAreSorted(a []int) bool { return IsSorted(IntArray(a)) } +func StringsAreSorted(a []string) bool { return IsSorted(StringArray(a)) } diff --git a/eBook/exercises/chapter_11/sort_persons.go b/eBook/exercises/chapter_11/sort_persons.go new file mode 100755 index 0000000..31b4a6d --- /dev/null +++ b/eBook/exercises/chapter_11/sort_persons.go @@ -0,0 +1,36 @@ +// sort_persons.go +package main + +import ( + "fmt" + "./sort" +) + +type Person struct { + firstName string + lastName string +} + +type Persons []Person + +func (p Persons) Len() int { return len(p) } + +func (p Persons) Less(i, j int) bool { + in := p[i].lastName + " " + p[i].firstName + jn := p[j].lastName + " " + p[j].firstName + return in < jn +} + +func (p Persons) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func main() { + p1 := Person{"Xavier","Papadopoulos"} + p2 := Person{"Chris","Naegels"} + p3 := Person{"John","Doe"} + arrP := Persons{p1,p2,p3} + fmt.Printf("Before sorting: %v\n", arrP) + sort.Sort(arrP) + fmt.Printf("After sorting: %v\n", arrP) +} diff --git a/eBook/exercises/chapter_11/stack/stack_general.go b/eBook/exercises/chapter_11/stack/stack_general.go new file mode 100755 index 0000000..da78464 --- /dev/null +++ b/eBook/exercises/chapter_11/stack/stack_general.go @@ -0,0 +1,39 @@ +// stack.go +package stack + +import "errors" + +type Stack []interface{} + +func (stack Stack) Len() int { + return len(stack) +} + +func (stack Stack) Cap() int { + return cap(stack) +} + +func (stack Stack) IsEmpty() bool { + return len(stack) == 0 +} + +func (stack *Stack) Push(e interface{}) { + *stack = append(*stack, e) +} + +func (stack Stack) Top() (interface{}, error) { + if len(stack) == 0 { + return nil, errors.New("stack is empty") + } + return stack[len(stack)-1], nil +} + +func (stack *Stack) Pop() (interface{}, error) { + stk := *stack // dereference to a local variable stk + if len(stk) == 0 { + return nil, errors.New("stack is empty") + } + top := stk[len(stk)-1] + *stack = stk[:len(stk)-1] // shrink the stack + return top, nil +} diff --git a/eBook/exercises/chapter_11/stack/stack_general_v2.go b/eBook/exercises/chapter_11/stack/stack_general_v2.go new file mode 100755 index 0000000..d1a6770 --- /dev/null +++ b/eBook/exercises/chapter_11/stack/stack_general_v2.go @@ -0,0 +1,28 @@ +// stack_general_v2.go +// Package collection implements a generic stack. +package collection + +// The zero value for Stack is an empty stack ready to use. +type Stack struct { + data []interface{} +} + +// Push adds x to the top of the stack. +func (s *Stack) Push(x interface{}) { + s.data = append(s.data, x) +} + +// Pop removes and returns the top element of the stack. +// It's a run-time error to call Pop on an empty stack. +func (s *Stack) Pop() interface{} { + i := len(s.data) - 1 + res := s.data[i] + s.data[i] = nil // to avoid memory leak + s.data = s.data[:i] + return res +} + +// Size returns the number of elements in the stack. +func (s *Stack) Size() int { + return len(s.data) +} \ No newline at end of file diff --git a/eBook/exercises/chapter_12/calculator.go b/eBook/exercises/chapter_12/calculator.go new file mode 100755 index 0000000..87b32fc --- /dev/null +++ b/eBook/exercises/chapter_12/calculator.go @@ -0,0 +1,53 @@ +// calculator.go +// example: calculate 3 + 4 = 7 as input: 3 ENTER 4 ENTER + ENTER --> result = 7, + +package main + +import ( + "fmt" + "strconv" + "bufio" + "os" + "./stack/stack" +) + +func main() { + buf := bufio.NewReader(os.Stdin) + calc1 := new(stack.Stack) + fmt.Println("Give a number, an operator (+, -, *, /), or q to stop:") + for { + token, err := buf.ReadString('\n') + if err != nil { + fmt.Println("Input error !") + os.Exit(1) + } + token = token[0:len(token)-2] // remove "\r\n" + // fmt.Printf("--%s--\n",token) // debug statement + switch { + case token == "q": // stop als invoer = "q" + fmt.Println("Calculator stopped") + return + case token >= "0" && token <= "999999": + i, _ := strconv.Atoi(token) + calc1.Push(i) + case token == "+": + q := calc1.Pop() + p := calc1.Pop() + fmt.Printf("The result of %d %s %d = %d\n", p, token, q, p + q) + case token == "-": + q := calc1.Pop() + p := calc1.Pop() + fmt.Printf("The result of %d %s %d = %d\n", p, token, q, p - q) + case token == "*": + q := calc1.Pop() + p := calc1.Pop() + fmt.Printf("The result of %d %s %d = %d\n", p, token, q, p * q) + case token == "/": + q := calc1.Pop() + p := calc1.Pop() + fmt.Printf("The result of %d %s %d = %d\n", p, token, q, p / q) + default: + fmt.Println("No valid input") + } + } +} diff --git a/eBook/exercises/chapter_12/cat_numbered.go b/eBook/exercises/chapter_12/cat_numbered.go new file mode 100755 index 0000000..774c58d --- /dev/null +++ b/eBook/exercises/chapter_12/cat_numbered.go @@ -0,0 +1,43 @@ +package main + +import ( + "os" + "io" + "fmt" + "bufio" + "flag" +) + +var numberFlag = flag.Bool("n", false, "number each line") + +func cat(r *bufio.Reader) { + i := 1 + for { + buf, err := r.ReadBytes('\n') + if err == io.EOF { + break + } + if *numberFlag { + fmt.Fprintf(os.Stdout, "%5d %s", i, buf) + i++ + } else { + fmt.Fprintf(os.Stdout, "%s", buf) + } + } + return +} + +func main() { + flag.Parse() + if flag.NArg() == 0 { + cat(bufio.NewReader(os.Stdin)) + } + for i := 0; i < flag.NArg(); i++ { + f, err := os.Open(flag.Arg(i)) + if err != nil { + fmt.Fprintf(os.Stderr, "%s:error reading from %s: %s\n", os.Args[0], flag.Arg(i), err.Error()) + continue + } + cat(bufio.NewReader(f)) + } +} diff --git a/eBook/exercises/chapter_12/degob.go b/eBook/exercises/chapter_12/degob.go new file mode 100755 index 0000000..31df21f --- /dev/null +++ b/eBook/exercises/chapter_12/degob.go @@ -0,0 +1,41 @@ +// degob.go +package main + +import ( + "bufio" + "fmt" + "encoding/gob" + "log" + "os" +) + +type Address struct { + Type string + City string + Country string +} + +type VCard struct { + FirstName string + LastName string + Addresses []*Address + Remark string +} + +var content string +var vc VCard + +func main() { + // using a decoder: + file, _ := os.Open("vcard.gob") + defer file.Close() + inReader := bufio.NewReader(file) + dec := gob.NewDecoder(inReader) + err := dec.Decode(&vc) + if err != nil { + log.Println("Error in decoding gob") + } + fmt.Println(vc) +} +// Output: +// {Jan Kersschot [0x12642e60 0x12642e80] none} \ No newline at end of file diff --git a/eBook/exercises/chapter_12/goprogram b/eBook/exercises/chapter_12/goprogram new file mode 100755 index 0000000..531ddb9 --- /dev/null +++ b/eBook/exercises/chapter_12/goprogram @@ -0,0 +1,10 @@ +// goprogram.go +package main + +import ( + "fmt" +) + +func main() { + fmt.Println("Hello World!") +} diff --git a/eBook/exercises/chapter_12/goprogramT b/eBook/exercises/chapter_12/goprogramT new file mode 100755 index 0000000000000000000000000000000000000000..279309adb2ae34d6b612d779d189d38a102da1f2 GIT binary patch literal 50 zcmY#L&*$Yz&Q9dz%FHd` 1 { // os.Args[0] == hello_who + who = strings.Join(os.Args[1:], " ") + } + fmt.Println("Hello", who, "!") +} diff --git a/eBook/exercises/chapter_12/products.txt b/eBook/exercises/chapter_12/products.txt new file mode 100755 index 0000000..84a9e54 --- /dev/null +++ b/eBook/exercises/chapter_12/products.txt @@ -0,0 +1,4 @@ +"The ABC of Go";25.5;1500 +"Functional Programming with Go";56;280 +"Go for It";45.9;356 +"The Go Way";55;500 \ No newline at end of file diff --git a/eBook/exercises/chapter_12/read_csv.go b/eBook/exercises/chapter_12/read_csv.go new file mode 100755 index 0000000..213a654 --- /dev/null +++ b/eBook/exercises/chapter_12/read_csv.go @@ -0,0 +1,67 @@ +// read_csv.go +package main + +import ( + "bufio" + "fmt" + "log" + "io" + "os" + "strconv" + "strings" +) + +type Book struct { + title string + price float64 + quantity int +} + +func main() { + bks := make([]Book, 1) + file, err := os.Open("products.txt") + if err != nil { + log.Fatalf("Error %s opening file products.txt: ", err) + } + defer file.Close() + + reader := bufio.NewReader(file) + for { + // read one line from the file: + line, err := reader.ReadString('\n') + if err == io.EOF { + break + } + // remove \r and \n so 2(in Windows, in Linux only \n, so 1): + line = string(line[:len(line)-2]) + //fmt.Printf("The input was: -%s-", line) + + strSl := strings.Split(line, ";") + book := new(Book) + book.title = strSl[0] + book.price, err = strconv.ParseFloat(strSl[1], 32) + if err!=nil { + fmt.Printf("Error in file: %v", err) + } + //fmt.Printf("The quan was:-%s-", strSl[2]) + book.quantity, err = strconv.Atoi(strSl[2]) + if err!=nil { + fmt.Printf("Error in file: %v", err) + } + if bks[0].title == "" { + bks[0] = *book + } else { + bks = append(bks, *book) + } + } + fmt.Println("We have read the following books from the file: ") + for _, bk := range bks { + fmt.Println(bk) + } +} +/* Output: +We have read the following books from the file: +{"The ABC of Go" 25.5 1500} +{"Functional Programming with Go" 56 280} +{"Go for It" 45.900001525878906 356} +*/ diff --git a/eBook/exercises/chapter_12/remove_3till5char.go b/eBook/exercises/chapter_12/remove_3till5char.go new file mode 100755 index 0000000..18f9055 --- /dev/null +++ b/eBook/exercises/chapter_12/remove_3till5char.go @@ -0,0 +1,37 @@ +// remove_first6char.go +package main + +import ( + "fmt" + "io" + "bufio" + "os" +) + +func main() { + inputFile, _ := os.Open("goprogram") + outputFile, _ := os.OpenFile("goprogramT", os.O_WRONLY|os.O_CREATE, 0666) + defer inputFile.Close() + defer outputFile.Close() + inputReader := bufio.NewReader(inputFile) + outputWriter := bufio.NewWriter(outputFile) + for { + // inputString, readerError := inputReader.ReadString('\n') + inputString, _, readerError := inputReader.ReadLine() + if readerError == io.EOF { + fmt.Println("EOF") + break + } + //fmt.Printf("The input was: --%s--", inputString) + outputString := string([]byte(inputString)[2:5]) + "\r\n" + //fmt.Printf("The output was: --%s--", outputString) + _, err := outputWriter.WriteString(outputString) + //fmt.Printf("Number of bytes written %d\n", n) + if (err != nil) { + fmt.Println(err) + return + } + } + outputWriter.Flush() + fmt.Println("Conversion done") +} diff --git a/eBook/exercises/chapter_12/stack/stack_struct.go b/eBook/exercises/chapter_12/stack/stack_struct.go new file mode 100755 index 0000000..08a58e4 --- /dev/null +++ b/eBook/exercises/chapter_12/stack/stack_struct.go @@ -0,0 +1,32 @@ +// stack_struct.go +package stack + +import "strconv" +const LIMIT = 10 + +type Stack struct { + ix int // first free position, so data[ix] == 0 + data [LIMIT]int +} + +func (st *Stack) Push(n int) { + if (st.ix + 1 > LIMIT) { + return // stack is full! + } + st.data[st.ix] = n + st.ix++ +} + +func (st *Stack) Pop() int { + st.ix-- + return st.data[st.ix] +} + +func (st Stack) String() string { + str := "" + for ix:=0; ixjhBO4TQ6wjOG)LpbDZpM+a^(z;3)I^VIi~Noqs(aB8-adRphH|Oq hi=*JYW{p95W<}XZ|87=xxV`qnk)rY59;ePbp&eo|KimKS literal 0 HcmV?d00001 diff --git a/eBook/exercises/chapter_12/word_letter_count.go b/eBook/exercises/chapter_12/word_letter_count.go new file mode 100755 index 0000000..405200b --- /dev/null +++ b/eBook/exercises/chapter_12/word_letter_count.go @@ -0,0 +1,37 @@ +// Q28_word_letter_count.go +package main + +import ( + "fmt" + "bufio" + "os" + "strings" +) +var nrchars, nrwords, nrlines int + +func main() { + nrchars, nrwords, nrlines = 0, 0, 0 + inputReader := bufio.NewReader(os.Stdin) + fmt.Println("Please enter some input, type S to stop: ") + for { + input, err := inputReader.ReadString('\n') + if err != nil { + fmt.Printf("An error occurred: %s\n", err) + } + if input == "S\r\n" { // Windows, on Linux it is "S\n" + fmt.Println("Here are the counts:") + fmt.Printf("Number of characters: %d\n", nrchars) + fmt.Printf("Number of words: %d\n", nrwords) + fmt.Printf("Number of lines: %d\n", nrlines) + os.Exit(0) + } + Counters(input) + } +} + +func Counters(input string) { + nrchars += len(input) - 2 // -2 for \r\n + // count number of spaces, nr of words is +1 + nrwords += strings.Count(input, " ") + 1 + nrlines++ +} diff --git a/eBook/exercises/chapter_13/Makefile b/eBook/exercises/chapter_13/Makefile new file mode 100755 index 0000000..96321be --- /dev/null +++ b/eBook/exercises/chapter_13/Makefile @@ -0,0 +1,6 @@ +include $(GOROOT)/src/Make.inc +TARG=strev +GOFILES=\ + string_reverse.go\ + +include $(GOROOT)/src/Make.pkg diff --git a/eBook/exercises/chapter_13/panic_defer.go b/eBook/exercises/chapter_13/panic_defer.go new file mode 100755 index 0000000..bca1761 --- /dev/null +++ b/eBook/exercises/chapter_13/panic_defer.go @@ -0,0 +1,44 @@ +// panic_defer.go +package main + +import "fmt" + +func main() { + f() + fmt.Println("Returned normally from f.") +} + +func f() { + defer func() { + if r := recover(); r != nil { + fmt.Println("Recovered in f", r) + } + }() + fmt.Println("Calling g.") + g(0) + fmt.Println("Returned normally from g.") +} + +func g(i int) { + if i > 3 { + fmt.Println("Panicking!") + panic(fmt.Sprintf("%v", i)) + } + defer fmt.Println("Defer in g", i) + fmt.Println("Printing in g", i) + g(i + 1) +} +/* Output: +Calling g. +Printing in g 0 +Printing in g 1 +Printing in g 2 +Printing in g 3 +Panicking! +Defer in g 3 +Defer in g 2 +Defer in g 1 +Defer in g 0 +Recovered in f 4 +Returned normally from f. +*/ diff --git a/eBook/exercises/chapter_13/panic_defer_convint.go b/eBook/exercises/chapter_13/panic_defer_convint.go new file mode 100755 index 0000000..db4012f --- /dev/null +++ b/eBook/exercises/chapter_13/panic_defer_convint.go @@ -0,0 +1,44 @@ +// panic_defer_convint.go +package main + +import ( + "fmt" + "math" +) + +func main() { + l := int64(15000) + if i, err := IntFromInt64(l); err!= nil { + fmt.Printf("The conversion of %d to an int32 resulted in an error: %s", l, err.Error()) + } else { + fmt.Printf("%d converted to an int32 is %d", l, i) + } + fmt.Println() + l = int64(math.MaxInt32 + 15000) + if i, err := IntFromInt64(l); err!= nil { + fmt.Printf("The conversion of %d to an int32 resulted in an error: %s", l, err.Error()) + } else { + fmt.Printf("%d converted to an int32 is %d", l, i) + } +} + +func ConvertInt64ToInt(l int64) int { + if math.MinInt32 <= l && l <= math.MaxInt32 { + return int(l) + } + panic(fmt.Sprintf("%d is out of the int32 range", l)) +} + +func IntFromInt64(l int64) (i int, err error) { + defer func() { + if e := recover(); e != nil { + err = fmt.Errorf("%v", e) + } + }() + i = ConvertInt64ToInt(l) + return i, nil +} +/* Output: +15000 converted to an int32 is 15000 +The conversion of 2147498647 to an int32 resulted in an error: 2147498647 is out of the int32 range +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_13/recover_divbyzero.go b/eBook/exercises/chapter_13/recover_divbyzero.go new file mode 100755 index 0000000..6a90d66 --- /dev/null +++ b/eBook/exercises/chapter_13/recover_divbyzero.go @@ -0,0 +1,34 @@ +// recover_divbyzero.go +package main + +import ( + "fmt" +) + +func badCall() { + a, b := 10, 0 + n := a / b + fmt.Println(n) +} + +func test() { + defer func() { + if e := recover(); e != nil { + fmt.Printf("Panicing %s\r\n", e); + } + + }() + badCall() + fmt.Printf("After bad call\r\n"); +} + +func main() { + fmt.Printf("Calling test\r\n"); + test() + fmt.Printf("Test completed\r\n"); +} +/* Output: +Calling test +Panicing runtime error: integer divide by zero +Test completed +*/ diff --git a/eBook/exercises/chapter_13/string_reverse.go b/eBook/exercises/chapter_13/string_reverse.go new file mode 100755 index 0000000..2069480 --- /dev/null +++ b/eBook/exercises/chapter_13/string_reverse.go @@ -0,0 +1,18 @@ +// string_reverse.go +package strev + +func Reverse(s string) string { + runes := []rune(s) + n, h := len(runes), len(runes)/2 + for i := 0; i < h; i++ { + runes[i], runes[n-1-i] = runes[n-1-i], runes[i] + } + return string(runes) +} + +/* +func main() { + s := "My Test String!" + fmt.Println(s, " --> ", Reverse(s)) +} +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_13/string_reverse_test.go b/eBook/exercises/chapter_13/string_reverse_test.go new file mode 100755 index 0000000..d767773 --- /dev/null +++ b/eBook/exercises/chapter_13/string_reverse_test.go @@ -0,0 +1,40 @@ +// string_reverse_test.go +package strev + +import "testing" +import "./strev" + +type ReverseTest struct { + in, out string +} + +var ReverseTests = []ReverseTest { + ReverseTest{"ABCD", "DCBA"}, + ReverseTest{"CVO-AZ", "ZA-OVC"}, + ReverseTest{"Hello 世界", "界世 olleH"}, +} + +func TestReverse(t *testing.T) { +/* + in := "CVO-AZ" + out := Reverse(in) + exp := "ZA-OVC" + if out != exp { + t.Errorf("Reverse of %s expects %s, but got %s", in, exp, out) + } +*/ +// testing with a battery of testdata: + for _, r := range ReverseTests { + exp := strev.Reverse(r.in) + if r.out != exp { + t.Errorf("Reverse of %s expects %s, but got %s", r.in, exp, r.out) + } + } +} + +func BenchmarkReverse(b *testing.B) { + s := "ABCD" + for i:=0; i < b.N; i++ { + strev.Reverse(s) + } +} diff --git a/eBook/exercises/chapter_14/blocking.go b/eBook/exercises/chapter_14/blocking.go new file mode 100755 index 0000000..3224ba1 --- /dev/null +++ b/eBook/exercises/chapter_14/blocking.go @@ -0,0 +1,19 @@ +// blocking.go +// throw: all goroutines are asleep - deadlock! +package main + +import ( + "fmt" +) + +func f1(in chan int) { + fmt.Println(<-in) +} + +func main() { + out := make(chan int) + //out := make(chan int, 1) // solution 2 + // go f1(out) // solution 1 + out <- 2 + go f1(out) +} diff --git a/eBook/exercises/chapter_14/channel_block3.go b/eBook/exercises/chapter_14/channel_block3.go new file mode 100755 index 0000000..00cfba7 --- /dev/null +++ b/eBook/exercises/chapter_14/channel_block3.go @@ -0,0 +1,22 @@ +package main + +import "fmt" +import "time" + +func main() { + c := make(chan int) + go func() { + time.Sleep(15 * 1e9) + x := <-c + fmt.Println("received", x) + }() + fmt.Println("sending", 10) + c <- 10 + fmt.Println("sent", 10) +} +/* Output: +sending 10 +(15 s later): +received 10 +sent 10 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_14/channel_buffer.go b/eBook/exercises/chapter_14/channel_buffer.go new file mode 100755 index 0000000..07e907b --- /dev/null +++ b/eBook/exercises/chapter_14/channel_buffer.go @@ -0,0 +1,21 @@ +package main + +import "fmt" +import "time" + +func main() { + c := make(chan int, 50) + go func() { + time.Sleep(15 * 1e9) + x := <-c + fmt.Println("received", x) + }() + fmt.Println("sending", 10) + c <- 10 + fmt.Println("sent", 10) +} +/* Output: +sending 10 +sent 10 // prints immediately +no further output, because main() then stops +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_14/concurrent_pi.go b/eBook/exercises/chapter_14/concurrent_pi.go new file mode 100755 index 0000000..7ea2d59 --- /dev/null +++ b/eBook/exercises/chapter_14/concurrent_pi.go @@ -0,0 +1,45 @@ +// Concurrent computation of pi. +// See http://goo.gl/ZuTZM. - Comparison with Scala! +// +// This demonstrates Go's ability to handle +// large numbers of concurrent processes. +// It is an unreasonable way to calculate pi. +package main + +import ( + "fmt" + "math" + "time" +) + +func main() { + start := time.Now() + fmt.Println(CalculatePi(5000)) + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} + +// CalculatePi launches n goroutines to compute an +// series-approximation of pi. +func CalculatePi(n int) float64 { + ch := make(chan float64) + for k := 0; k <= n; k++ { + // calculate k-th term in the series + go term(ch, float64(k)) + } + f := 0.0 + //wait for all goroutines to complete, get and sum up their results: + for k := 0; k <= n; k++ { + f += <-ch + } + return f +} + +func term(ch chan float64, k float64) { + ch <- 4 * math.Pow(-1, k) / (2*k + 1) +} +/* Output: +3.14179261359579 +The calculation took this amount of time: 0.028002 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_14/concurrent_pi2.go b/eBook/exercises/chapter_14/concurrent_pi2.go new file mode 100755 index 0000000..621f148 --- /dev/null +++ b/eBook/exercises/chapter_14/concurrent_pi2.go @@ -0,0 +1,45 @@ +// concurrent_pi2.go +package main + +import ( + "fmt" + "math" + "runtime" + "time" +) + +const NCPU = 2 + +func main() { + start := time.Now() + runtime.GOMAXPROCS(2) + fmt.Println(CalculatePi(5000)) + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} + +func CalculatePi(end int) float64 { + ch := make(chan float64) + for i := 0; i < NCPU; i++ { + go term(ch, i*end/NCPU, (i+1)*end/NCPU) + } + result := 0.0 + for i := 0; i < NCPU; i++ { + result += <-ch + } + return result +} + +func term(ch chan float64, start, end int) { + result := 0.0 + for i := start; i < end; i++ { + x := float64(i) + result += 4 * (math.Pow(-1, x) / (2.0*x + 1.0)) + } + ch <- result +} +/* Output: +3.1413926535917938 +The calculation took this amount of time: 0.002000 +*/ diff --git a/eBook/exercises/chapter_14/general_lazy_evalution2.go b/eBook/exercises/chapter_14/general_lazy_evalution2.go new file mode 100755 index 0000000..e51ff6c --- /dev/null +++ b/eBook/exercises/chapter_14/general_lazy_evalution2.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" +) + +type Any interface{} +type EvalFunc func(Any) (Any, Any) + +func main() { + fibFunc := func(state Any) (Any, Any) { + os := state.([]uint64) + v1 := os[0] + v2 := os[1] + ns := []uint64{v2, v1 + v2} + return v1, ns + } + fib := BuildLazyUInt64Evaluator(fibFunc, []uint64{0, 1}) + + for i := 0; i < 10; i++ { + fmt.Printf("Fib nr %v: %v\n", i, fib()) + } +} + +func BuildLazyEvaluator(evalFunc EvalFunc, initState Any) func() Any { + retValChan := make(chan Any) + loopFunc := func() { + var actState Any = initState + var retVal Any + for { + retVal, actState = evalFunc(actState) + retValChan <- retVal + } + } + retFunc := func() Any { + return <-retValChan + } + go loopFunc() + return retFunc +} + +func BuildLazyUInt64Evaluator(evalFunc EvalFunc, initState Any) func() uint64 { + ef := BuildLazyEvaluator(evalFunc, initState) + return func() uint64 { + return ef().(uint64) + } +} +/* Output: +Fib nr 0: 0 +Fib nr 1: 1 +Fib nr 2: 1 +Fib nr 3: 2 +Fib nr 4: 3 +Fib nr 5: 5 +Fib nr 6: 8 +Fib nr 7: 13 +Fib nr 8: 21 +Fib nr 9: 34 +*/ diff --git a/eBook/exercises/chapter_14/gofibonacci.go b/eBook/exercises/chapter_14/gofibonacci.go new file mode 100755 index 0000000..8dc6e0a --- /dev/null +++ b/eBook/exercises/chapter_14/gofibonacci.go @@ -0,0 +1,44 @@ +// Q26_fibonacci_go.go +package main + +import ( + "fmt" + "time" + "os" +) + +func main() { + term := 25 + i := 0 + c := make(chan int) + start := time.Now() + + go fibnterms(term, c) + for { + if result, ok := <-c; ok { + fmt.Printf("fibonacci(%d) is: %d\n", i, result) + i++ + } else { + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) + os.Exit(0) + } + } +} + +func fibnterms(term int, c chan int) { + for i := 0; i <= term; i++ { + c <- fibonacci(i) + } + close(c) +} + +func fibonacci(n int) (res int) { + if n <= 1 { + res = 1 + } else { + res = fibonacci(n-1) + fibonacci(n-2) + } + return +} diff --git a/eBook/exercises/chapter_14/gofibonacci2.go b/eBook/exercises/chapter_14/gofibonacci2.go new file mode 100755 index 0000000..46e7a59 --- /dev/null +++ b/eBook/exercises/chapter_14/gofibonacci2.go @@ -0,0 +1,35 @@ +// gofibonacci2.go +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) + } +} +/* Output: +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +*/ diff --git a/eBook/exercises/chapter_14/gofibonacci3.go b/eBook/exercises/chapter_14/gofibonacci3.go new file mode 100755 index 0000000..8560a3f --- /dev/null +++ b/eBook/exercises/chapter_14/gofibonacci3.go @@ -0,0 +1,45 @@ +// courtesy of: http://sdh33b.blogspot.com/2009/12/fibonacci-in-go.html +package main + +import ( + "fmt" + "time" +) + +func dup3(in <-chan int) (<-chan int, <-chan int, <-chan int) { + a, b, c := make(chan int, 2), make(chan int, 2), make(chan int, 2) + go func() { + for { + x := <-in + a <- x + b <- x + c <- x + } + }() + return a, b, c +} + +func fib() <-chan int { + x := make(chan int, 2) + a, b, out := dup3(x) + go func() { + x <- 0 + x <- 1 + <-a + for { + x <- <-a + <-b + } + }() + return out +} + +func main() { + start := time.Now() + x := fib() + for i := 0; i < 10; i++ { + fmt.Println(<-x) + } + end := time.Now() + delta := end.Sub(start) + fmt.Printf("longCalculation took this amount of time: %s\n", delta) +} diff --git a/eBook/exercises/chapter_14/gofibonacci_select.go b/eBook/exercises/chapter_14/gofibonacci_select.go new file mode 100755 index 0000000..1811d14 --- /dev/null +++ b/eBook/exercises/chapter_14/gofibonacci_select.go @@ -0,0 +1,42 @@ +// gofibonacci_select.go +package main + +import "fmt" + +func fibonacci(c, quit chan int) { + x, y := 1, 1 + for { + select { + case c <- x: + x, y = y, x+y + case <-quit: + fmt.Println("quit") + return + } + } +} + +func main() { + c := make(chan int) + quit := make(chan int) + go func() { + for i := 0; i < 10; i++ { + fmt.Println(<-c) + } + quit <- 0 + }() + fibonacci(c, quit) +} +/* Output: +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +quit +*/ diff --git a/eBook/exercises/chapter_14/goroutine_close.go b/eBook/exercises/chapter_14/goroutine_close.go new file mode 100755 index 0000000..56ea4e1 --- /dev/null +++ b/eBook/exercises/chapter_14/goroutine_close.go @@ -0,0 +1,26 @@ +// Q20_goroutine.go +package main + +import ( + "fmt" +) + +func tel(ch chan int) { + for i:=0; i < 15; i++ { + ch <- i + } + close(ch) // if this is ommitted: panic: all goroutines are asleep - deadlock! +} + +func main() { + var ok = true + var i int + ch := make(chan int) + + go tel(ch) + for ok { + if i, ok= <-ch; ok { + fmt.Printf("ok is %t and the counter is at %d\n", ok, i) + } + } +} diff --git a/eBook/exercises/chapter_14/goroutine_panic.go b/eBook/exercises/chapter_14/goroutine_panic.go new file mode 100755 index 0000000..a9783dd --- /dev/null +++ b/eBook/exercises/chapter_14/goroutine_panic.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" +) + +func tel(ch chan int) { + for i := 0; i < 15; i++ { + ch <- i + } +} + +func main() { + var ok = true + ch := make(chan int) + + go tel(ch) + for ok { + i := <-ch + fmt.Printf("ok is %t and the counter is at %d\n", ok, i) + } +} diff --git a/eBook/exercises/chapter_14/goroutine_select.go b/eBook/exercises/chapter_14/goroutine_select.go new file mode 100755 index 0000000..5e2c7da --- /dev/null +++ b/eBook/exercises/chapter_14/goroutine_select.go @@ -0,0 +1,31 @@ +// Q20b_goroutine.go +package main + +import ( + "fmt" + "os" +) + +func tel(ch chan int, quit chan bool) { + for i:=0; i < 15; i++ { + ch <- i + } + quit <- true +} + +func main() { + var ok = true + ch := make(chan int) + quit := make(chan bool) + + go tel(ch, quit) + for ok { + select { + case i:= <-ch: + fmt.Printf("The counter is at %d\n", i) + case <-quit: + os.Exit(0) + } + } +} + diff --git a/eBook/exercises/chapter_14/gosum.go b/eBook/exercises/chapter_14/gosum.go new file mode 100755 index 0000000..53271f8 --- /dev/null +++ b/eBook/exercises/chapter_14/gosum.go @@ -0,0 +1,16 @@ +// gosum.go +package main + +import ( + "fmt" +) + +func sum(x, y int, c chan int) { + c <- x + y +} + +func main() { + c := make(chan int) + go sum(12, 13, c) + fmt.Println(<-c) // 25 +} diff --git a/eBook/exercises/chapter_14/multiplex_server3.go b/eBook/exercises/chapter_14/multiplex_server3.go new file mode 100755 index 0000000..6d1c2e5 --- /dev/null +++ b/eBook/exercises/chapter_14/multiplex_server3.go @@ -0,0 +1,58 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package main + +import "fmt" + +type Request struct { + a, b int + replyc chan int // reply channel inside the Request +} + +type binOp func(a, b int) int + +func run(op binOp, req *Request) { + req.replyc <- op(req.a, req.b) +} + +func (r *Request) String() string { + return fmt.Sprintf("%d+%d=%d", r.a, r.b, <-r.replyc) +} + +func server(op binOp, service chan *Request, quit chan bool) { + for { + select { + case req := <-service: + go run(op, req) + case <-quit: + return // stop infinite loop + } + } +} + +func startServer(op binOp) (service chan *Request, quit chan bool) { + service = make(chan *Request) + quit = make(chan bool) + go server(op, service, quit) + return service, quit +} + +func main() { + adder, quit := startServer(func(a, b int) int { return a + b }) + // make requests: + req1 := &Request{3, 4, make(chan int)} + req2 := &Request{150, 250, make(chan int)} + // send requests on the service channel + adder <- req1 + adder <- req2 + // ask for the results: ( method String() is called ) + fmt.Println(req1, req2) + // shutdown server: + quit <- true + fmt.Print("done") +} +/* output: +3+4=7 150+250=400 +done +*/ diff --git a/eBook/exercises/chapter_14/polar_to_cartesian.go b/eBook/exercises/chapter_14/polar_to_cartesian.go new file mode 100755 index 0000000..01be44f --- /dev/null +++ b/eBook/exercises/chapter_14/polar_to_cartesian.go @@ -0,0 +1,101 @@ +// polartocartesian.go +package main + +import ( + "bufio" + "fmt" + "math" + "os" + "runtime" + "strconv" + "strings" +) + +type polar struct { + radius float64 + Θ float64 +} + +type cartesian struct { + x float64 + y float64 +} + +const result = "Polar: radius=%.02f angle=%.02f degrees -- Cartesian: x=%.02f y=%.02f\n" + +var prompt = "Enter a radius and an angle (in degrees), e.g., 12.5 90, " + "or %s to quit." + +func init() { + if runtime.GOOS == "windows" { + prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter") + } else { // Unix-like + prompt = fmt.Sprintf(prompt, "Ctrl+D") + } +} + +func main() { + questions := make(chan polar) + defer close(questions) + answers := createSolver(questions) + defer close(answers) + interact(questions, answers) +} + +func createSolver(questions chan polar) chan cartesian { + answers := make(chan cartesian) + go func() { + for { + polarCoord := <-questions + Θ := polarCoord.Θ * math.Pi / 180.0 // degrees to radians + x := polarCoord.radius * math.Cos(Θ) + y := polarCoord.radius * math.Sin(Θ) + answers <- cartesian{x, y} + } + }() + return answers +} + +func interact(questions chan polar, answers chan cartesian) { + reader := bufio.NewReader(os.Stdin) + fmt.Println(prompt) + for { + fmt.Printf("Radius and angle: ") + line, err := reader.ReadString('\n') + if err != nil { + break + } + line = line[:len(line)-1] // chop of newline character + if numbers := strings.Fields(line); len(numbers) == 2 { + polars, err := floatsForStrings(numbers) + if err != nil { + fmt.Fprintln(os.Stderr, "invalid number") + continue + } + questions <- polar{polars[0], polars[1]} + coord := <-answers + fmt.Printf(result, polars[0], polars[1], coord.x, coord.y) + } else { + fmt.Fprintln(os.Stderr, "invalid input") + } + } + fmt.Println() +} + +func floatsForStrings(numbers []string) ([]float64, error) { + var floats []float64 + for _, number := range numbers { + if x, err := strconv.ParseFloat(number, 64); err != nil { + return nil, err + } else { + floats = append(floats, x) + } + } + return floats, nil +} +/* Output: +Enter a radius and an angle (in degrees), e.g., 12.5 90, or Ctrl+Z, Enter to qui +t. +Radius and angle: 12.5 90 +Polar: radius=12.50 angle=90.00 degrees -- Cartesian: x=0.00 y=12.50 +Radius and angle: ^Z +*/ diff --git a/eBook/exercises/chapter_14/producer_consumer.go b/eBook/exercises/chapter_14/producer_consumer.go new file mode 100755 index 0000000..465dae2 --- /dev/null +++ b/eBook/exercises/chapter_14/producer_consumer.go @@ -0,0 +1,42 @@ +// goroutines2.go +package main + +import "fmt" + +// integer producer: +func numGen(start, count int, out chan<- int) { + for i := 0; i < count; i++ { + out <- start + start = start + count + } + close(out) +} + +// integer consumer: +func numEchoRange(in <-chan int, done chan<- bool) { + for num := range in { + fmt.Printf("%d\n", num) + } + done <- true +} + +func main() { + numChan := make(chan int) + done := make(chan bool) + go numGen(0, 10, numChan) + go numEchoRange(numChan, done) + + <-done +} +/* Output: +0 +10 +20 +30 +40 +50 +60 +70 +80 +90 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_14/producer_consumer2.go b/eBook/exercises/chapter_14/producer_consumer2.go new file mode 100755 index 0000000..353daa3 --- /dev/null +++ b/eBook/exercises/chapter_14/producer_consumer2.go @@ -0,0 +1,29 @@ +// prod_cons.go +/* producer-consumer problem in Go */ +package main + +import "fmt" + +var done = make(chan bool) +var msgs = make(chan int) + +func produce() { + for i := 0; i < 10; i++ { + msgs <- i + } + done <- true +} + +func consume() { + for { + msg := <-msgs + fmt.Print(msg, " ") + } +} + +func main() { + go produce() + go consume() + <-done +} +// Output: 0 1 2 3 4 5 6 7 8 9 \ No newline at end of file diff --git a/eBook/exercises/chapter_14/random_bitgen.go b/eBook/exercises/chapter_14/random_bitgen.go new file mode 100755 index 0000000..5a31efe --- /dev/null +++ b/eBook/exercises/chapter_14/random_bitgen.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" +) + +func main() { + c := make(chan int) + // consumer: + go func() { + for { + fmt.Print(<-c, " ") + } + }() + // producer: + for { + select { + case c <- 0: + case c <- 1: + } + } + +} diff --git a/eBook/exercises/chapter_15/client1.go b/eBook/exercises/chapter_15/client1.go new file mode 100755 index 0000000..179aee4 --- /dev/null +++ b/eBook/exercises/chapter_15/client1.go @@ -0,0 +1,46 @@ +package main + +import ( + "fmt" + "os" + "net" + "bufio" + "strings" +) + +func main() { + var conn net.Conn + var error error + var inputReader *bufio.Reader + var input string + var clientName string + + // maak connectie met de server: + conn, error = net.Dial("tcp", "localhost:50000") + checkError(error) + + inputReader = bufio.NewReader(os.Stdin) + fmt.Println("First, what is your name?") + clientName, _ = inputReader.ReadString('\n') + // fmt.Printf("CLIENTNAME %s",clientName) + trimmedClient := strings.Trim(clientName, "\r\n") // "\r\n" voor Windows, "\n" voor Linux + + for { + fmt.Println("What to send to the server? Type Q to quit. Type SH to shutdown server.") + input, _ = inputReader.ReadString('\n') + trimmedInput := strings.Trim(input, "\r\n") + // fmt.Printf("input:--%s--",input) + // fmt.Printf("trimmedInput:--%s--",trimmedInput) + if trimmedInput == "Q" { + return + } + _, error = conn.Write([]byte(trimmedClient + " says: " + trimmedInput)) + checkError(error) + } +} + +func checkError(error error) { + if error != nil { + panic("Error: " + error.Error()) // terminate program + } +} \ No newline at end of file diff --git a/eBook/exercises/chapter_15/hello_server.go b/eBook/exercises/chapter_15/hello_server.go new file mode 100755 index 0000000..fbeb8a3 --- /dev/null +++ b/eBook/exercises/chapter_15/hello_server.go @@ -0,0 +1,19 @@ +// hello_server.go +package main + +import ( + "fmt" + "net/http" +) + +type Hello struct{} + +func (h Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "Hello!") +} + +func main() { + var h Hello + http.ListenAndServe("localhost:4000",h) +} +// Output in browser-window with url http://localhost:4000: Hello! diff --git a/eBook/exercises/chapter_15/http_fetch2.go b/eBook/exercises/chapter_15/http_fetch2.go new file mode 100755 index 0000000..8ef2c0b --- /dev/null +++ b/eBook/exercises/chapter_15/http_fetch2.go @@ -0,0 +1,31 @@ +// httpfetch.go +package main + +import ( + "bufio" + "fmt" + "net/http" + "io/ioutil" + "log" + "os" + "strings" +) + +func main() { + fmt.Print("Give the url from which to read: ") + iread := bufio.NewReader(os.Stdin) + url, _ := iread.ReadString('\n') + url = strings.Trim(url," \n\r") // trimming space,etc. + // fmt.Println("***", url,"***") // debugging + res, err := http.Get(url) + CheckError(err) + data, err := ioutil.ReadAll(res.Body) + CheckError(err) + fmt.Printf("Got: %q", string(data)) +} + +func CheckError(err error) { + if err != nil { + log.Fatalf("Get: %v", err) + } +} diff --git a/eBook/exercises/chapter_15/server1.go b/eBook/exercises/chapter_15/server1.go new file mode 100755 index 0000000..5ffa2bf --- /dev/null +++ b/eBook/exercises/chapter_15/server1.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + "os" + "net" + "strings" +) + +// Map of the clients: contains: clientname - 1 (active) / 0 - (inactive) +var mapUsers map[string]int + +func main() { + var listener net.Listener + var error error + var conn net.Conn + mapUsers = make(map[string]int) + + fmt.Println("Starting the server ...") + + // create listener: + listener, error = net.Listen("tcp", "localhost:50000") + checkError(error) + // listen and accept connections from clients: + for { + conn, error = listener.Accept() + checkError(error) + go doServerStuff(conn) + } +} + +func doServerStuff(conn net.Conn) { + var buf []byte + var error error + + for { + buf = make([]byte, 512) + _, error = conn.Read(buf) + checkError(error) + input := string(buf) + if strings.Contains(input, ": SH") { + fmt.Println("Server shutting down.") + os.Exit(0) + } + // op commando WHO: write out mapUsers + if strings.Contains(input, ": WHO") { + DisplayList() + } + // extract clientname: + ix := strings.Index(input, "says") + clName := input[0:ix-1] + //fmt.Printf("The clientname is ---%s---\n", string(clName)) + // set clientname active in mapUsers: + mapUsers[string(clName)] = 1 + fmt.Printf("Received data: --%v--", string(buf)) + } +} + +// advantage: code is cleaner, +// disadvantage: the server process has to stop at any error: +// a simple return continues in the function where we came from! +func checkError(error error) { + if error != nil { + panic("Error: " + error.Error()) // terminate program + } +} + +func DisplayList() { + fmt.Println("--------------------------------------------") + fmt.Println("This is the client list: 1=active, 0=inactive") + for key, value := range mapUsers { + fmt.Printf("User %s is %d\n", key, value) + } + fmt.Println("--------------------------------------------") +} diff --git a/eBook/exercises/chapter_15/statistics.go b/eBook/exercises/chapter_15/statistics.go new file mode 100755 index 0000000..a280923 --- /dev/null +++ b/eBook/exercises/chapter_15/statistics.go @@ -0,0 +1,104 @@ +// statistics.go +package main + +import ( + "fmt" + "net/http" + "sort" + "strings" + "strconv" + "log" +) + +type statistics struct { + numbers []float64 + mean float64 + median float64 +} + +const form = `
    +
    +
    + +
    ` + +const error = `

    %s

    ` + +var pageTop = "" +var pageBottom = "" + +func main() { + http.HandleFunc("/", homePage) + if err := http.ListenAndServe(":9001", nil); err != nil { + log.Fatal("failed to start server", err) + } +} + +func homePage(writer http.ResponseWriter, request *http.Request) { + writer.Header().Set("Content-Type", "text/html") + err := request.ParseForm() // Must be called before writing response + fmt.Fprint(writer, pageTop, form) + if err != nil { + fmt.Fprintf(writer, error, err) + } else { + if numbers, message, ok := processRequest(request); ok { + stats := getStats(numbers) + fmt.Fprint(writer, formatStats(stats)) + } else if message != "" { + fmt.Fprintf(writer, error, message) + } + } + fmt.Fprint(writer, pageBottom) +} + +func processRequest(request *http.Request) ([]float64, string, bool) { + var numbers []float64 + if slice, found := request.Form["numbers"]; found && len(slice) > 0 { + text := strings.Replace(slice[0], ",", " ", -1) + for _, field := range strings.Fields(text) { + if x, err := strconv.ParseFloat(field, 64); err != nil { + return numbers, "'" + field + "' is invalid", false + } else { + numbers = append(numbers, x) + } + } + } + if len(numbers) == 0 { + return numbers, "", false // no data first time form is shown + } + return numbers, "", true +} + +func getStats(numbers []float64) (stats statistics) { + stats.numbers = numbers + sort.Float64s(stats.numbers) + stats.mean = sum(numbers) / float64(len(numbers)) + stats.median = median(numbers) + return +} + +func sum(numbers []float64) (total float64) { + for _, x := range numbers { + total += x + } + return +} + +func median(numbers []float64) float64 { + middle := len(numbers)/2 + result := numbers[middle] + if len(numbers)%2 == 0 { + result = (result + numbers[middle-1]) / 2 + } + return result +} + +func formatStats(stats statistics) string { + return fmt.Sprintf(` + + + + + +
    Results
    Numbers%v
    Count%d
    Mean%f
    Median%f
    `, stats.numbers, len(stats.numbers), stats.mean, stats.median) +} diff --git a/eBook/exercises/chapter_15/template_validation_recover.go b/eBook/exercises/chapter_15/template_validation_recover.go new file mode 100755 index 0000000..2159188 --- /dev/null +++ b/eBook/exercises/chapter_15/template_validation_recover.go @@ -0,0 +1,29 @@ +// template_validation_recover.go +package main + +import ( + "text/template" + "fmt" + "log" +) + +func main() { + tOk := template.New("ok") + tErr := template.New("error_template") + defer func() { + if err := recover(); err != nil { + log.Printf("run time panic: %v", err) + } + }() + + //a valid template, so no panic with Must: + template.Must(tOk.Parse("/* and a comment */ some static text: {{ .Name }}")) + fmt.Println("The first one parsed OK.") + fmt.Println("The next one ought to fail.") + template.Must(tErr.Parse(" some static text {{ .Name }")) +} +/* Output: +The first one parsed OK. +The next one ought to fail. +2011/10/27 10:56:27 run time panic: template: error_template:1: unexpected "}" in command +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_15/twitter_status_json.go b/eBook/exercises/chapter_15/twitter_status_json.go new file mode 100755 index 0000000..2dc1319 --- /dev/null +++ b/eBook/exercises/chapter_15/twitter_status_json.go @@ -0,0 +1,33 @@ +// twitter_status_json.go +package main + +import ( + "net/http" + "fmt" + "encoding/json" + "io/ioutil" +) + +type Status struct { + Text string +} + +type User struct { + Status Status +} + +func main() { + /* perform an HTTP request for the twitter status of user: Googland */ + res, _:= http.Get("http://twitter.com/users/Googland.json") + /* initialize the structure of the JSON response */ + user := User{Status{""}} + /* unmarshal the JSON into our structures */ + temp, _ := ioutil.ReadAll(res.Body) + body := []byte(temp) + json.Unmarshal(body, &user) + fmt.Printf("status: %s", user.Status.Text) +} +/* Output: +status: Robot cars invade California, on orders from Google: +Google has been testing self-driving cars ... http://bit.ly/cbtpUN http://retwt.me/97p +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_15/webhello2.go b/eBook/exercises/chapter_15/webhello2.go new file mode 100755 index 0000000..b026a59 --- /dev/null +++ b/eBook/exercises/chapter_15/webhello2.go @@ -0,0 +1,24 @@ +// webhello2.go +package main + +import ( + "net/http" + "fmt" + "strings" +) + +func helloHandler(w http.ResponseWriter, r *http.Request) { + remPartOfURL := r.URL.Path[len("/hello/"):] //get everything after the /hello/ part of the URL + fmt.Fprintf(w, "Hello %s!", remPartOfURL) +} + +func shouthelloHandler(w http.ResponseWriter, r *http.Request) { + remPartOfURL := r.URL.Path[len("/shouthello/"):] //get everything after the /shouthello/ part of the URL + fmt.Fprintf(w, "Hello %s!", strings.ToUpper(remPartOfURL)) +} + +func main() { + http.HandleFunc("/hello/", helloHandler) + http.HandleFunc("/shouthello/", shouthelloHandler) + http.ListenAndServe("localhost:9999", nil) +} diff --git a/eBook/exercises/chapter_4/count_characters.go b/eBook/exercises/chapter_4/count_characters.go old mode 100644 new mode 100755 index 8df046b..1fc0ce2 --- a/eBook/exercises/chapter_4/count_characters.go +++ b/eBook/exercises/chapter_4/count_characters.go @@ -1,22 +1,22 @@ -package main - -import ( - "fmt" - "unicode/utf8" -) - -func main() { - // count number of characters: - str1 := "asSASA ddd dsjkdsjs dk" - fmt.Printf("The number of bytes in string str1 is %d\n",len(str1)) - fmt.Printf("The number of characters in string str1 is %d\n",utf8.RuneCountInString(str1)) - str2 := "asSASA ddd dsjkdsjsこん dk" - fmt.Printf("The number of bytes in string str2 is %d\n",len(str2)) - fmt.Printf("The number of characters in string str2 is %d",utf8.RuneCountInString(str2)) -} -/* Output: -The number of bytes in string str1 is 22 -The number of characters in string str1 is 22 -The number of bytes in string str2 is 28 -The number of characters in string str2 is 24 +package main + +import ( + "fmt" + "unicode/utf8" +) + +func main() { + // count number of characters: + str1 := "asSASA ddd dsjkdsjs dk" + fmt.Printf("The number of bytes in string str1 is %d\n",len(str1)) + fmt.Printf("The number of characters in string str1 is %d\n",utf8.RuneCountInString(str1)) + str2 := "asSASA ddd dsjkdsjsこん dk" + fmt.Printf("The number of bytes in string str2 is %d\n",len(str2)) + fmt.Printf("The number of characters in string str2 is %d",utf8.RuneCountInString(str2)) +} +/* Output: +The number of bytes in string str1 is 22 +The number of characters in string str1 is 22 +The number of bytes in string str2 is 28 +The number of characters in string str2 is 24 */ \ No newline at end of file diff --git a/eBook/exercises/chapter_4/divby0.go b/eBook/exercises/chapter_4/divby0.go old mode 100644 new mode 100755 index 5a87c36..36cfe6c --- a/eBook/exercises/chapter_4/divby0.go +++ b/eBook/exercises/chapter_4/divby0.go @@ -1,8 +1,8 @@ -package main - -func main() { - a, b := 10, 0 - c := a / b // panic: runtime error: integer divide by zero - - print(c) -} +package main + +func main() { + a, b := 10, 0 + c := a / b // panic: runtime error: integer divide by zero + + print(c) +} diff --git a/eBook/exercises/chapter_4/function_calls_function.go b/eBook/exercises/chapter_4/function_calls_function.go old mode 100644 new mode 100755 index f405dae..62711a4 --- a/eBook/exercises/chapter_4/function_calls_function.go +++ b/eBook/exercises/chapter_4/function_calls_function.go @@ -1,18 +1,18 @@ -package main - -var a string // global scope - -func main() { - a = "G" - print(a) - f1() -} -func f1() { - a := "O" // new local variable a, only scoped within f1() ! - print(a) - f2() -} -func f2() { - print(a) // global variable is taken -} +package main + +var a string // global scope + +func main() { + a = "G" + print(a) + f1() +} +func f1() { + a := "O" // new local variable a, only scoped within f1() ! + print(a) + f2() +} +func f2() { + print(a) // global variable is taken +} // GOG \ No newline at end of file diff --git a/eBook/exercises/chapter_4/global_scope.go b/eBook/exercises/chapter_4/global_scope.go old mode 100644 new mode 100755 index 9973d90..080a295 --- a/eBook/exercises/chapter_4/global_scope.go +++ b/eBook/exercises/chapter_4/global_scope.go @@ -1,19 +1,19 @@ -package main - -var a = "G" // global scope - -func main() { - n() - m() - n() -} - -func n() { - print(a) -} - -func m() { - a = "O" // simple assignment: global a gets a new value - print(a) -} +package main + +var a = "G" // global scope + +func main() { + n() + m() + n() +} + +func n() { + print(a) +} + +func m() { + a = "O" // simple assignment: global a gets a new value + print(a) +} // GOO \ No newline at end of file diff --git a/eBook/exercises/chapter_4/local_scope.go b/eBook/exercises/chapter_4/local_scope.go old mode 100644 new mode 100755 index 4f8bc03..785bf7e --- a/eBook/exercises/chapter_4/local_scope.go +++ b/eBook/exercises/chapter_4/local_scope.go @@ -1,17 +1,17 @@ -package main - -var a = "G" // global (package) scope - -func main() { - n() - m() - n() -} -func n() { - print(a) -} -func m() { - a := "O" // new local variable a is declared - print(a) -} +package main + +var a = "G" // global (package) scope + +func main() { + n() + m() + n() +} +func n() { + print(a) +} +func m() { + a := "O" // new local variable a is declared + print(a) +} // GOG \ No newline at end of file diff --git a/eBook/exercises/chapter_5/bitwise_complement.go b/eBook/exercises/chapter_5/bitwise_complement.go old mode 100644 new mode 100755 index c2c2c56..d113263 --- a/eBook/exercises/chapter_5/bitwise_complement.go +++ b/eBook/exercises/chapter_5/bitwise_complement.go @@ -1,22 +1,22 @@ -package main - -import "fmt" - -func main() { - for i:=0; i <= 10; i ++ { - fmt.Printf("the complement of %b is: %b\n", i, ^i) - } -} -/* Output: -the complement of 0 is: -1 -the complement of 1 is: -10 -the complement of 10 is: -11 -the complement of 11 is: -100 -the complement of 100 is: -101 -the complement of 101 is: -110 -the complement of 110 is: -111 -the complement of 111 is: -1000 -the complement of 1000 is: -1001 -the complement of 1001 is: -1010 -the complement of 1010 is: -1011 +package main + +import "fmt" + +func main() { + for i:=0; i <= 10; i ++ { + fmt.Printf("the complement of %b is: %b\n", i, ^i) + } +} +/* Output: +the complement of 0 is: -1 +the complement of 1 is: -10 +the complement of 10 is: -11 +the complement of 11 is: -100 +the complement of 100 is: -101 +the complement of 101 is: -110 +the complement of 110 is: -111 +the complement of 111 is: -1000 +the complement of 1000 is: -1001 +the complement of 1001 is: -1010 +the complement of 1010 is: -1011 */ \ No newline at end of file diff --git a/eBook/exercises/chapter_5/fizzbuzz.go b/eBook/exercises/chapter_5/fizzbuzz.go old mode 100644 new mode 100755 index 8b30374..ffa16dc --- a/eBook/exercises/chapter_5/fizzbuzz.go +++ b/eBook/exercises/chapter_5/fizzbuzz.go @@ -1,24 +1,24 @@ -package main - -import "fmt" - -const ( - FIZZ=3 - BUZZ=5 - FIZZBUZZ=15 -) - -func main() { - for i:=0; i <= 100; i++ { - switch { - case i%FIZZBUZZ==0: - fmt.Println("FizzBuzz") - case i%FIZZ==0: - fmt.Println("Fizz") - case i%BUZZ==0: - fmt.Println("Buzz") - default: - fmt.Println(i) - } - } +package main + +import "fmt" + +const ( + FIZZ=3 + BUZZ=5 + FIZZBUZZ=15 +) + +func main() { + for i:=0; i <= 100; i++ { + switch { + case i%FIZZBUZZ==0: + fmt.Println("FizzBuzz") + case i%FIZZ==0: + fmt.Println("Fizz") + case i%BUZZ==0: + fmt.Println("Buzz") + default: + fmt.Println(i) + } + } } \ No newline at end of file diff --git a/eBook/exercises/chapter_5/for_character.go b/eBook/exercises/chapter_5/for_character.go old mode 100644 new mode 100755 index 98979a4..2653f38 --- a/eBook/exercises/chapter_5/for_character.go +++ b/eBook/exercises/chapter_5/for_character.go @@ -1,17 +1,17 @@ -package main - -func main() { - // 1 - use 2 nested for loops - for i:=1; i <= 25; i++ { - for j:=1; j <=i; j++ { - print("G") - } - println() - } - // 2 - use only one for loop and string concatenation - str := "G" - for i:=1; i <= 25; i++ { - println(str) - str += "G" - } +package main + +func main() { + // 1 - use 2 nested for loops + for i:=1; i <= 25; i++ { + for j:=1; j <=i; j++ { + print("G") + } + println() + } + // 2 - use only one for loop and string concatenation + str := "G" + for i:=1; i <= 25; i++ { + println(str) + str += "G" + } } \ No newline at end of file diff --git a/eBook/exercises/chapter_5/for_loop.go b/eBook/exercises/chapter_5/for_loop.go old mode 100644 new mode 100755 index b7eeb95..a484f65 --- a/eBook/exercises/chapter_5/for_loop.go +++ b/eBook/exercises/chapter_5/for_loop.go @@ -1,16 +1,16 @@ -package main - -import "fmt" - -func main() { - // 1: - for i:=0; i < 15; i++ { - fmt.Printf("The counter is at %d\n", i) - } - // 2: - i := 0 -START: - fmt.Printf("The counter is at %d\n", i) - i++ - if i < 15 { goto START } +package main + +import "fmt" + +func main() { + // 1: + for i:=0; i < 15; i++ { + fmt.Printf("The counter is at %d\n", i) + } + // 2: + i := 0 +START: + fmt.Printf("The counter is at %d\n", i) + i++ + if i < 15 { goto START } } \ No newline at end of file diff --git a/eBook/exercises/chapter_5/i_undefined.go b/eBook/exercises/chapter_5/i_undefined.go old mode 100644 new mode 100755 index d4b47e9..d0c8840 --- a/eBook/exercises/chapter_5/i_undefined.go +++ b/eBook/exercises/chapter_5/i_undefined.go @@ -1,14 +1,14 @@ -// i_undefined.go -package main - -import ( - "fmt" -) - -func main() { - var i int - for i=0; i<10; i++ { - fmt.Printf("%v\n", i) - } - fmt.Printf("%v\n", i) //<-- compile error: undefined i -} +// i_undefined.go +package main + +import ( + "fmt" +) + +func main() { + var i int + for i=0; i<10; i++ { + fmt.Printf("%v\n", i) + } + fmt.Printf("%v\n", i) //<-- compile error: undefined i +} diff --git a/eBook/exercises/chapter_5/multiple_for.go b/eBook/exercises/chapter_5/multiple_for.go old mode 100644 new mode 100755 index 2e7f3d9..b9b0649 --- a/eBook/exercises/chapter_5/multiple_for.go +++ b/eBook/exercises/chapter_5/multiple_for.go @@ -1,17 +1,17 @@ -// multiple_for.go -package main - -import "fmt" - -func main() { - //multiple initialization; a consolidated bool expression with && and ||; multiple ‘incrementation’ - for i, j, s := 0, 5, "a"; i < 3 && j < 100 && s != "aaaaa"; i, j, s = i+1, - j+1, s + "a" { - fmt.Println("Value of i, j, s:", i, j, s) - } -} -/* Output: -Value of i, j, s: 0 5 a -Value of i, j, s: 1 6 aa -Value of i, j, s: 2 7 aaa +// multiple_for.go +package main + +import "fmt" + +func main() { + //multiple initialization; a consolidated bool expression with && and ||; multiple ‘incrementation’ + for i, j, s := 0, 5, "a"; i < 3 && j < 100 && s != "aaaaa"; i, j, s = i+1, + j+1, s + "a" { + fmt.Println("Value of i, j, s:", i, j, s) + } +} +/* Output: +Value of i, j, s: 0 5 a +Value of i, j, s: 1 6 aa +Value of i, j, s: 2 7 aaa */ \ No newline at end of file diff --git a/eBook/exercises/chapter_5/rectangle_stars.go b/eBook/exercises/chapter_5/rectangle_stars.go old mode 100644 new mode 100755 index bb5def0..a5eb7cb --- a/eBook/exercises/chapter_5/rectangle_stars.go +++ b/eBook/exercises/chapter_5/rectangle_stars.go @@ -1,26 +1,26 @@ -// rectangle_stars.go -package main - -import "fmt" - -func main() { - w, h := 20, 10 - for y := 0; y < h; y++ { - for x := 0; x < w; x++ { - fmt.Print("*") - } - fmt.Println() - } -} -/* Output: -******************** -******************** -******************** -******************** -******************** -******************** -******************** -******************** -******************** -******************** -*/ +// rectangle_stars.go +package main + +import "fmt" + +func main() { + w, h := 20, 10 + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + fmt.Print("*") + } + fmt.Println() + } +} +/* Output: +******************** +******************** +******************** +******************** +******************** +******************** +******************** +******************** +******************** +******************** +*/ diff --git a/eBook/exercises/chapter_5/season.go b/eBook/exercises/chapter_5/season.go old mode 100644 new mode 100755 index 1a21bed..ba200d5 --- a/eBook/exercises/chapter_5/season.go +++ b/eBook/exercises/chapter_5/season.go @@ -1,17 +1,17 @@ -package main - -import "fmt" - -func main() { - fmt.Printf(Season(3)) -} - -func Season(month int) string { - switch month { - case 12,1,2: return "Winter" - case 3,4,5: return "Spring" - case 6,7,8: return "Summer" - case 9,10,11: return "Autumn" - } - return "Season unknown" +package main + +import "fmt" + +func main() { + fmt.Printf(Season(3)) +} + +func Season(month int) string { + switch month { + case 12,1,2: return "Winter" + case 3,4,5: return "Spring" + case 6,7,8: return "Summer" + case 9,10,11: return "Autumn" + } + return "Season unknown" } \ No newline at end of file diff --git a/eBook/exercises/chapter_6/10to1_recursive.go b/eBook/exercises/chapter_6/10to1_recursive.go new file mode 100755 index 0000000..fa0d40b --- /dev/null +++ b/eBook/exercises/chapter_6/10to1_recursive.go @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + printrec(1) +} + +func printrec(i int) { + if i>10 { return } + printrec(i+1) + fmt.Printf("%d ", i) +} \ No newline at end of file diff --git a/eBook/exercises/chapter_6/compose.go b/eBook/exercises/chapter_6/compose.go new file mode 100755 index 0000000..dfaa491 --- /dev/null +++ b/eBook/exercises/chapter_6/compose.go @@ -0,0 +1,17 @@ +// compose.go +package main + +import ( + "fmt" + "math" +) + +func Compose(f, g func(x float64) float64) func(x float64) float64 { + return func(x float64) float64 { // closure + return f(g(x)) + } +} + +func main() { + fmt.Print(Compose(math.Sin, math.Cos)(0.5)) // output: 0.7691963548410085 +} diff --git a/eBook/exercises/chapter_6/error_returnval.go b/eBook/exercises/chapter_6/error_returnval.go old mode 100644 new mode 100755 index 87a3ed2..6ef8cc7 --- a/eBook/exercises/chapter_6/error_returnval.go +++ b/eBook/exercises/chapter_6/error_returnval.go @@ -1,43 +1,56 @@ -package main - -import ( - "errors" - "fmt" - "math" -) - -func MySqrt1(a float64) (Sqrt float64, Err error) { - if a < 0 { - Err = errors.New("Fuck!") - Sqrt = 0 - return - } - Sqrt = math.Sqrt(a) - return -} - -func MySqrt2(a float64) (float64, error) { - var Sqrt float64 - var Err error - if a < 0 { - Err = errors.New("Fuck!") - Sqrt = 0 - return Sqrt, Err - } - Sqrt = math.Sqrt(a) - return Sqrt, Err -} - -func main() { - var a float64 = 99.99 - var b float64 = -99.99 - Sqrt11, Err11 := MySqrt1(a) - Sqrt12, Err12 := MySqrt1(b) - Sqrt21, Err21 := MySqrt2(a) - Sqrt22, Err22 := MySqrt2(b) - - fmt.Println(Sqrt11, Err11) - fmt.Println(Sqrt12, Err12) - fmt.Println(Sqrt21, Err21) - fmt.Println(Sqrt22, Err22) -} +// error_returnval.go +package main + +import ( + "errors" + "fmt" + "math" +) + +func main() { + fmt.Print("First example with -1: ") + ret1, err1 := MySqrt(-1) + if err1 != nil { + fmt.Println("Error! Return values are: ", ret1, err1) + } else { + fmt.Println("It's ok! Return values are: ", ret1, err1) + } + + fmt.Print("Second example with 5: ") + //you could also write it like this + if ret2, err2 := MySqrt(5); err2 != nil { + fmt.Println("Error! Return values are: ", ret2, err2) + } else { + fmt.Println("It's ok! Return values are: ", ret2, err2) + } + // named return variables: + fmt.Println(MySqrt2(5)) +} + +func MySqrt(f float64) (float64, error) { + //return an error as second parameter if invalid input + if (f < 0) { + return float64(math.NaN()), errors.New("I won't be able to do a sqrt of negative number!") + } + //otherwise use default square root function + return math.Sqrt(f), nil +} + +//name the return variables - by default it will have 'zero-ed' values i.e. numbers are 0, string is empty, etc. +func MySqrt2(f float64) (ret float64, err error) { + if (f < 0) { + //then you can use those variables in code + ret = float64(math.NaN()) + err = errors.New("I won't be able to do a sqrt of negative number!") + } else { + ret = math.Sqrt(f) + //err is not assigned, so it gets default value nil + } + //automatically return the named return variables ret and err + return +} +/* Output: +First example with -1: Error! Return values are: NaN I won't be able to do a sqrt of negative number! +Second example with 5: It's ok! Return values are: 2.23606797749979 +2.23606797749979 +*/ diff --git a/eBook/exercises/chapter_6/factorial.go b/eBook/exercises/chapter_6/factorial.go new file mode 100755 index 0000000..eeaac81 --- /dev/null +++ b/eBook/exercises/chapter_6/factorial.go @@ -0,0 +1,34 @@ +// factorial.go +package main + +import ( + "fmt" +) + +func main() { + for i := uint64(0); i < uint64(30); i++ { + fmt.Printf("Factorial of %d is %d\n", i, Factorial(i)) + } +} + +/* unnamed return variables: +func Factorial(n uint64) uint64 { + if n > 0 { + return n * Factorial(n-1) + } + return 1 +} +*/ + +// named return variables: +func Factorial(n uint64) (fac uint64) { + fac = 1 + if n > 0 { + fac = n * Factorial(n-1) + return + } + return +} + +// int: correct results till 12! +// uint64: correct results till 21! diff --git a/eBook/exercises/chapter_6/fibonacci2.go b/eBook/exercises/chapter_6/fibonacci2.go new file mode 100755 index 0000000..6fde9be --- /dev/null +++ b/eBook/exercises/chapter_6/fibonacci2.go @@ -0,0 +1,24 @@ +package main + +import "fmt" + +func main() { + pos := 4 + result, pos := fibonacci(pos) + fmt.Printf("the %d-th fibonacci number is: %d\n", pos, result) + pos = 10 + result, pos = fibonacci(pos) + fmt.Printf("the %d-th fibonacci number is: %d\n", pos, result) +} + +func fibonacci(n int) (val, pos int) { + if n <= 1 { + val = 1 + } else { + v1, _ := fibonacci(n-1) + v2, _ := fibonacci(n-2) + val = v1 + v2 + } + pos = n + return +} diff --git a/eBook/exercises/chapter_6/fibonacci_closure.go b/eBook/exercises/chapter_6/fibonacci_closure.go new file mode 100755 index 0000000..cc29b96 --- /dev/null +++ b/eBook/exercises/chapter_6/fibonacci_closure.go @@ -0,0 +1,20 @@ +package main + +// fib returns a function that returns +// successive Fibonacci numbers. +func fib() func() int { + a, b := 1, 1 + return func() int { + a, b = b, a+b + return b + } +} + +func main() { + f := fib() + // Function calls are evaluated left-to-right. + // println(f(), f(), f(), f(), f()) + for i:=0; i<=9; i++ { + println(i+2, f() ) + } +} diff --git a/eBook/exercises/chapter_6/function_filter2.go b/eBook/exercises/chapter_6/function_filter2.go new file mode 100755 index 0000000..30a2dd7 --- /dev/null +++ b/eBook/exercises/chapter_6/function_filter2.go @@ -0,0 +1,37 @@ +// function_filter2.go +package main + +import "fmt" + +type flt func(int) bool + +// func isEven(n int) bool { if n%2 == 0 { return true }; return false } +func isEven(n int) bool { + if n%2 == 0 { + return true + } + return false +} + +func filter(sl []int, f flt) (yes, no []int) { + for _, val := range sl { + if f(val) { + yes = append(yes, val) + } else { + no = append(no, val) + } + } + return +} + +func main() { + slice := []int{1, 2, 3, 4, 5, 7} + fmt.Println("slice = ", slice) + even, odd := filter(slice, isEven) + fmt.Println("The even elements of slice are: ", even) + fmt.Println("The odd elements of slice are: ", odd) +} + +/* + +*/ diff --git a/eBook/exercises/chapter_6/lambda_value.go b/eBook/exercises/chapter_6/lambda_value.go new file mode 100755 index 0000000..0b0d803 --- /dev/null +++ b/eBook/exercises/chapter_6/lambda_value.go @@ -0,0 +1,18 @@ +// lambda_value.go +package main + +import ( + "fmt" +) + +func main() { + fv := func() { + fmt.Println("Hello World!") + } + fv() + fmt.Printf("The type of fv is %T", fv) +} +/* Output: +Hello World! +The type of fv is func() +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_6/mult_returnval.go b/eBook/exercises/chapter_6/mult_returnval.go old mode 100644 new mode 100755 index b6e62da..fbdde34 --- a/eBook/exercises/chapter_6/mult_returnval.go +++ b/eBook/exercises/chapter_6/mult_returnval.go @@ -1,27 +1,24 @@ -package main - -import "fmt" - -func MultReturn1(a, b int) (Sum, Mul, Dif int) { - Sum = a + b - Mul = a * b - Dif = a - b - return -} - -func MultReturn2(a, b int) (int, int, int) { - Sum := a + b - Mul := a * b - Dif := a - b - return Sum, Mul, Dif - -} - -func main() { - a := 100 - b := 78 - Sum1, Mul1, Dif1 := MultReturn1(a, b) - Sum2, Mul2, Dif2 := MultReturn2(a, b) - fmt.Println("Named:", Sum1, Mul1, Dif1) - fmt.Println("Unnamed:", Sum2, Mul2, Dif2) -} +// mult_returnval.go +package main + +import ( + "fmt" +) + +func SumProductDiff(i, j int) (int, int, int) { + return i+j, i*j, i-j +} + +func SumProductDiffN(i, j int) (s int, p int, d int) { + s, p, d = i+j, i*j, i-j + return +} + +func main() { + sum, prod, diff := SumProductDiff(3,4) + fmt.Println("Sum:", sum, "| Product:",prod, "| Diff:", diff) + sum, prod, diff = SumProductDiffN(3,4) + fmt.Println("Sum:", sum, "| Product:",prod, "| Diff:", diff) +} +// Sum: 7 | Product: 12 | Diff: -1 +// Sum: 7 | Product: 12 | Diff: -1 \ No newline at end of file diff --git a/eBook/exercises/chapter_6/strings_map.go b/eBook/exercises/chapter_6/strings_map.go new file mode 100755 index 0000000..ea82d8a --- /dev/null +++ b/eBook/exercises/chapter_6/strings_map.go @@ -0,0 +1,13 @@ +// strings_map.go +package main + +import ( + "fmt" + "strings" +) + +func main() { + asciiOnly := func(c rune) rune { if c > 127 { return ' ' }; return c } + fmt.Println(strings.Map(asciiOnly, "Jérôme Österreich")) +} +// J r me sterreich \ No newline at end of file diff --git a/eBook/exercises/chapter_6/varargs.go b/eBook/exercises/chapter_6/varargs.go new file mode 100755 index 0000000..0c2eb70 --- /dev/null +++ b/eBook/exercises/chapter_6/varargs.go @@ -0,0 +1,23 @@ +// Q10_varargs.go +package main + +import ( + "fmt" +) + +func main() { + printInts() + println() + printInts(2, 3) + println() + printInts(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) +} + +func printInts(list ...int) { +// for i:=0; i sl[i+1] { + sl[i], sl[i+1] = sl[i+1], sl[i] + } + } + } +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/fibonacci_array.go b/eBook/exercises/chapter_7/fibonacci_array.go new file mode 100755 index 0000000..50c065b --- /dev/null +++ b/eBook/exercises/chapter_7/fibonacci_array.go @@ -0,0 +1,18 @@ +package main + +import "fmt" + +var fibs [50]int64 + +func main() { + fibs[0] = 1 + fibs[1] = 1 + + for i:= 2; i < 50; i++ { + fibs[i] = fibs[i-1] + fibs[i-2] + } + + for i:=0; i < 50; i++ { + fmt.Printf("The %d-th Fibonacci number is: %d\n", i, fibs[i]) + } +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/fibonacci_funcarray.go b/eBook/exercises/chapter_7/fibonacci_funcarray.go new file mode 100755 index 0000000..b5cd653 --- /dev/null +++ b/eBook/exercises/chapter_7/fibonacci_funcarray.go @@ -0,0 +1,22 @@ +package main + +import "fmt" + +var term = 15 + +func main() { + result := fibarray(term) + for ix, fib := range result { + fmt.Printf("The %d-th Fibonacci number is: %d\n", ix, fib) + } +} + +func fibarray(term int) []int { + farr := make([]int, term) + farr[0], farr[1] = 1, 1 + + for i:= 2; i < term; i++ { + farr[i] = farr[i-1] + farr[i-2] + } + return farr +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/filter_slice.go b/eBook/exercises/chapter_7/filter_slice.go new file mode 100755 index 0000000..59ff196 --- /dev/null +++ b/eBook/exercises/chapter_7/filter_slice.go @@ -0,0 +1,32 @@ +// filter_slice.go +package main + +import ( + "fmt" +) + +func main() { + s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + s = Filter(s, even) + fmt.Println(s) +} + +// Filter returns a new slice holding only +// the elements of s that satisfy f() +func Filter(s []int, fn func(int) bool) []int { + var p []int // == nil + for _, i := range s { + if fn(i) { + p = append(p, i) + } + } + return p +} + +func even(n int) bool { + if n%2 == 0 { + return true + } + return false +} +/* [0 2 4 6 8] */ diff --git a/eBook/exercises/chapter_7/for_array.go b/eBook/exercises/chapter_7/for_array.go new file mode 100755 index 0000000..b93c3af --- /dev/null +++ b/eBook/exercises/chapter_7/for_array.go @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + var arr [15]int + for i:=0; i < 15; i++ { + arr[i] = i + } + fmt.Println(arr) // [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14] + + +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/insert_slice.go b/eBook/exercises/chapter_7/insert_slice.go new file mode 100755 index 0000000..5d35d31 --- /dev/null +++ b/eBook/exercises/chapter_7/insert_slice.go @@ -0,0 +1,23 @@ +// insert_slice.go +package main + +import ( + "fmt" +) + +func main() { + s := []string{"M", "N", "O", "P", "Q", "R"} + in := []string{"A", "B", "C"} + res := InsertStringSlice(s, in, 0) // at the front + fmt.Println(res) // [A B C M N O P Q R] + res = InsertStringSlice(s, in, 3) // [M N O A B C P Q R] + fmt.Println(res) +} + +func InsertStringSlice(slice, insertion []string, index int) []string { + result := make([]string, len(slice) + len(insertion)) + at := copy(result, slice[:index]) + at += copy(result[at:], insertion) + copy(result[at:], slice[index:]) + return result +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/magnify_slice.go b/eBook/exercises/chapter_7/magnify_slice.go new file mode 100755 index 0000000..4b6e13c --- /dev/null +++ b/eBook/exercises/chapter_7/magnify_slice.go @@ -0,0 +1,25 @@ +package main + +import "fmt" + +var s []int + +func main() { + s = []int{1, 2, 3} + fmt.Println("The length of s before enlarging is:", len(s)) + fmt.Println(s) + s = enlarge(s, 5) + fmt.Println("The length of s after enlarging is:", len(s)) + fmt.Println(s) +} + +func enlarge(s []int, factor int) []int { + ns := make([]int, len(s) * factor) + // fmt.Println("The length of ns is:", len(ns)) + copy(ns, s) + //fmt.Println(ns) + s = ns + //fmt.Println(s) + //fmt.Println("The length of s after enlarging is:", len(s)) + return s +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/map_function.go b/eBook/exercises/chapter_7/map_function.go new file mode 100755 index 0000000..30b3ab9 --- /dev/null +++ b/eBook/exercises/chapter_7/map_function.go @@ -0,0 +1,32 @@ +package main + +import "fmt" + +func main() { + list := []int{0, 1, 2, 3, 4, 5, 6, 7} + mf := func(i int) int { + return i * 10 + } + /* + result := mapFunc(mf, list) + for _, v := range result { + fmt.Println(v) + } + */ + println() + // shorter: + fmt.Printf("%v", mapFunc(mf, list) ) +} + +func mapFunc(mf func(int) int, list []int) ([]int) { + result := make([]int, len(list)) + for ix, v := range list { + result[ix] = mf(v) + } + /* + for ix := 0; ix max { + max = v + } + } + return +} + +func minSlice(sl [] int) (min int) { + // min = int(^uint(0) >> 1) + min = math.MaxInt32 + for _, v := range sl { + if v < min { + min = v + } + } + return +} +/* Output: +The maximum is 643 +The minimum is 2 +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_7/remove_slice.go b/eBook/exercises/chapter_7/remove_slice.go new file mode 100755 index 0000000..d5c93d1 --- /dev/null +++ b/eBook/exercises/chapter_7/remove_slice.go @@ -0,0 +1,19 @@ +// remove_slice.go +package main + +import ( + "fmt" +) + +func main() { + s := []string{"M", "N", "O", "P", "Q", "R"} + res := RemoveStringSlice(s, 2, 4) + fmt.Println(res) // [M N Q R] +} + +func RemoveStringSlice(slice []string, start, end int) []string { + result := make([]string, len(slice) - (end - start)) + at := copy(result, slice[:start]) + copy(result[at:], slice[end:]) + return result +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/split_string.go b/eBook/exercises/chapter_7/split_string.go new file mode 100755 index 0000000..24634fb --- /dev/null +++ b/eBook/exercises/chapter_7/split_string.go @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func main() { + str := "Google" + for i:=0; i <= len(str); i++ { + a, b := Split(str, i) + fmt.Printf("The string %s split at position %d is: %s / %s\n", str, i, a, b) + } + +} + +func Split(s string, pos int) (string, string) { + return s[0:pos], s[pos:] +} \ No newline at end of file diff --git a/eBook/exercises/chapter_7/string_reverse.go b/eBook/exercises/chapter_7/string_reverse.go new file mode 100755 index 0000000..053fc2d --- /dev/null +++ b/eBook/exercises/chapter_7/string_reverse.go @@ -0,0 +1,41 @@ +package main + +import "fmt" + +func reverse(s string) string { + runes := []rune(s) + n, h := len(runes), len(runes)/2 + for i:= 0; i < h; i ++ { + runes[i], runes[n-1-i] = runes[n-1-i], runes[i] + } + return string(runes) +} + +func main() { +// reverse a string: + str := "Google" + sl := []byte(str) + var rev [100]byte + j := 0 + for i:=len(sl)-1; i >= 0; i-- { + rev[j] = sl[i] + j++ + } + str_rev := string(rev[:]) + fmt.Printf("The reversed string is -%s-\n", str_rev) +// variant: "in place" using swapping + str2 := "Google" + sl2 := []byte(str2) + for i, j := 0, len(sl2) - 1; i < j; i, j = i+1, j-1 { + sl2[i], sl2[j] = sl2[j], sl2[i] + } + fmt.Printf("The reversed string is -%s-\n", string(sl2)) +// variant: using [] int for runes (necessary for Unicode-strings!): + s := "My Test String!" + fmt.Println(s, " --> ", reverse(s)) +} +/* Output: +The reversed string is -elgooG- +The reversed string is -elgooG- +My Test String! --> !gnirtS tseT yM +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_7/string_split2.go b/eBook/exercises/chapter_7/string_split2.go new file mode 100755 index 0000000..77e812e --- /dev/null +++ b/eBook/exercises/chapter_7/string_split2.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + str := "Google" + str2 := Split2(str) + fmt.Printf("The string %s transformed is: %s\n", str, str2) +} + +func Split2(s string) string { + mid := len(s) / 2 + return s[mid:] + s[:mid] +} +// Output: The string Google transformed is: gleGoo \ No newline at end of file diff --git a/eBook/exercises/chapter_7/sum_array.go b/eBook/exercises/chapter_7/sum_array.go new file mode 100755 index 0000000..d1cb723 --- /dev/null +++ b/eBook/exercises/chapter_7/sum_array.go @@ -0,0 +1,39 @@ +// leaving out the length 4 in [4] uses slice instead of an array +// which is generally better for performance +package main + +import "fmt" + +func main() { + // var a = [4]float32 {1.0,2.0,3.0,4.0} + var a = []float32 {1.0,2.0,3.0,4.0} + fmt.Printf("The sum of the array is: %f\n", Sum(a)) + var b = []int {1, 2, 3, 4, 5} + sum, average := SumAndAverage(b) + fmt.Printf("The sum of the array is: %d, and the average is: %f", sum, average) +} + +/* +func Sum(a [4]float32) (sum float32) { + for _, item := range a { + sum += item + } + return +} +*/ + +func Sum(a []float32) (sum float32) { + for _, item := range a { + sum += item + } + return +} + +func SumAndAverage (a []int) (int, float32) { + sum := 0 + for _, item := range a { + sum += item + } + return sum, float32(sum/len(a)) +} + diff --git a/eBook/exercises/chapter_7/uniq.go b/eBook/exercises/chapter_7/uniq.go new file mode 100755 index 0000000..b4c2aed --- /dev/null +++ b/eBook/exercises/chapter_7/uniq.go @@ -0,0 +1,23 @@ +// Q29_uniq.go +package main + +import ( + "fmt" +) + +var arr []byte = []byte{'a','b','a','a','a','c','d','e','f','g'} + +func main() { + arru := make([]byte,len(arr)) // this will contain the unique items + ixu := 0 // index in arru + tmp := byte(0) + for _, val := range arr { + if val!=tmp { + arru[ixu] = val + fmt.Printf("%c ", arru[ixu]) + ixu++ + } + tmp = val + } + // fmt.Println(arru) +} diff --git a/eBook/exercises/chapter_8/map_days.go b/eBook/exercises/chapter_8/map_days.go new file mode 100755 index 0000000..7c4fa70 --- /dev/null +++ b/eBook/exercises/chapter_8/map_days.go @@ -0,0 +1,35 @@ +// map_days.go +package main + +import ( + "fmt" +) + +var Days = map[int]string{1:"monday", + 2:"tuesday", + 3: "wednesday", + 4: "thursday", + 5: "friday", + 6: "saturday", + 7: "sunday"} + +func main() { + fmt.Println(Days) + // fmt.Printf("%v", Days) + flagHolliday := false + for k, v := range Days { + if v == "thursday" || v == "holliday" { + fmt.Println(v, " is the ", k , "th day in the week") + if v == "holliday" { + flagHolliday = true + } + } + } + if !flagHolliday { + fmt.Println("holliday is not a day!") + } +} +/* Output: +thursday is the 4 th day in the week +holliday is not a day! +*/ \ No newline at end of file diff --git a/eBook/exercises/chapter_8/map_drinks.go b/eBook/exercises/chapter_8/map_drinks.go new file mode 100755 index 0000000..e048055 --- /dev/null +++ b/eBook/exercises/chapter_8/map_drinks.go @@ -0,0 +1,73 @@ +// map_drinks.go +package main + +import ( + "fmt" + "sort" +) + +func main() { + drinks := map[string]string{ + "beer": "bière", + "wine": "vin", + "water": "eau", + "coffee": "café", + "thea": "thé"} + sdrinks := make([]string, len(drinks)) + ix := 0 + + fmt.Printf("The following drinks are available:\n") + for eng := range drinks { + sdrinks[ix] = eng + ix++ + fmt.Println(eng) + } + + fmt.Println("") + for eng, fr := range drinks { + fmt.Printf("The french for %s is %s\n", eng, fr) + } + + // SORTING: + fmt.Println("") + fmt.Println("Now the sorted output:") + sort.Strings(sdrinks) + + fmt.Printf("The following sorted drinks are available:\n") + for _, eng := range sdrinks { + fmt.Println(eng) + } + + fmt.Println("") + for _, eng := range sdrinks { + fmt.Printf("The french for %s is %s\n", eng, drinks[eng]) + } +} +/* Output: +The following drinks are available: +wine +beer +water +coffee +thea + +The french for wine is vin +The french for beer is bière +The french for water is eau +The french for coffee is café +The french for thea is thé + +Now the sorted output: +The following sorted drinks are available: +beer +coffee +thea +water +wine + +The french for beer is bière +The french for coffee is café +The french for thea is thé +The french for water is eau +The french for wine is vin +*/ diff --git a/eBook/exercises/chapter_9/dlinked_list.go b/eBook/exercises/chapter_9/dlinked_list.go new file mode 100755 index 0000000..10eaff2 --- /dev/null +++ b/eBook/exercises/chapter_9/dlinked_list.go @@ -0,0 +1,28 @@ +// Q20_linked_list.go +package main + +import ( + "fmt" + "container/list" +) + +func main() { + lst := list.New() + lst.PushBack(100) + lst.PushBack(101) + lst.PushBack(102) + // fmt.Println("Here is the double linked list:\n", lst) + for e := lst.Front(); e != nil; e = e.Next() { + // fmt.Println(e) + fmt.Println(e.Value) + } +} +/* Example output: +&{0x12542bc0 0x12547590 1} +&{0x12542ba0 0x12542be0 0x12547590 2} +&{ 0x12542bc0 0x12547590 4} + +100 +101 +102 +*/ diff --git a/eBook/exercises/chapter_9/even/even.go b/eBook/exercises/chapter_9/even/even.go new file mode 100755 index 0000000..142da1b --- /dev/null +++ b/eBook/exercises/chapter_9/even/even.go @@ -0,0 +1,6 @@ +// even.go +package even + +func Even(i int) bool { // exported function + return i%2 == 0 +} diff --git a/eBook/exercises/chapter_9/fibo/fibonacci.go b/eBook/exercises/chapter_9/fibo/fibonacci.go new file mode 100755 index 0000000..e95f900 --- /dev/null +++ b/eBook/exercises/chapter_9/fibo/fibonacci.go @@ -0,0 +1,33 @@ +package fibo + +/* +func Fibonacci(n int) (res int) { + if n <= 1 { + res = 1 + } else { + res = Fibonacci(n-1) + Fibonacci(n-2) + } + return +} +*/ +// accepts a general operation op: +func Fibonacci(op string, n int) (res int) { + if n <= 1 { + switch op { + case "+": + res = 1 + case "*": + res = 2 + default: res = 0 + } + } else { + switch op { + case "+": + res = Fibonacci(op, n-1) + Fibonacci(op, n-2) + case "*": + res = Fibonacci(op, n-1) * Fibonacci(op, n-2) + default: res = 0 + } + } + return +} diff --git a/eBook/exercises/chapter_9/greetings/greetings.go b/eBook/exercises/chapter_9/greetings/greetings.go new file mode 100755 index 0000000..c7a72e0 --- /dev/null +++ b/eBook/exercises/chapter_9/greetings/greetings.go @@ -0,0 +1,27 @@ +package greetings + +import "time" + +func GoodDay(name string) string { + return "Good Day " + name +} + +func GoodNight(name string) string{ + return "Good Night " + name +} + +func IsAM() bool { + localTime := time.Now() + return localTime.Hour() <= 12 +} + +func IsAfternoon() bool { + localTime := time.Now() + return localTime.Hour() <= 18 +} + +func IsEvening() bool { + localTime := time.Now() + return localTime.Hour() <= 22 +} + diff --git a/eBook/exercises/chapter_9/main_fibo.go b/eBook/exercises/chapter_9/main_fibo.go new file mode 100755 index 0000000..b92423d --- /dev/null +++ b/eBook/exercises/chapter_9/main_fibo.go @@ -0,0 +1,62 @@ +package main + +import ( + "fmt" + "./fibo/fibo" +) + +var nextFibo int +var op string + +func main() { + /* + result := 0 + for i:=0; i <= 10; i++ { + result = fibo.Fibonacci(i) + fmt.Printf("fibonacci(%d) is: %d\n", i, result) + } + */ + op = "+" + calls() + fmt.Println("Change of operation from + to *") + nextFibo = 0 + op = "*" + calls() +} + +func calls() { + next() + fmt.Println("...") + next() + fmt.Println("...") + next() + fmt.Println("...") + next() +} + +func next() { + result := 0 + nextFibo++ + result = fibo.Fibonacci(op, nextFibo) + fmt.Printf("fibonacci(%d) is: %d\n", nextFibo, result) +} +/* ***************************************************************** +Output is: +fibonacci(1) is: 1 +... +fibonacci(2) is: 2 +... +fibonacci(3) is: 3 +... +fibonacci(4) is: 5 +Change of operation from + to * +fibonacci(1) is: 2 +... +fibonacci(2) is: 4 +... +fibonacci(3) is: 8 +... +fibonacci(4) is: 32 +********************************************************************/ + + diff --git a/eBook/exercises/chapter_9/main_greetings.go b/eBook/exercises/chapter_9/main_greetings.go new file mode 100755 index 0000000..bd29198 --- /dev/null +++ b/eBook/exercises/chapter_9/main_greetings.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + "./greetings/greetings" +) + +func main() { + name := "James" + fmt.Println(greetings.GoodDay(name)) + fmt.Println(greetings.GoodNight(name)) + + if greetings.IsAM() { + fmt.Println("Good morning", name) + } else if greetings.IsAfternoon(){ + fmt.Println("Good afternoon", name) + } else if greetings.IsEvening(){ + fmt.Println("Good evening", name) + } else { + fmt.Println("Good night", name) + } +} diff --git a/eBook/exercises/chapter_9/main_oddeven.go b/eBook/exercises/chapter_9/main_oddeven.go new file mode 100755 index 0000000..a3e8991 --- /dev/null +++ b/eBook/exercises/chapter_9/main_oddeven.go @@ -0,0 +1,13 @@ +// test_oddeven.go +package main + +import ( + "fmt" + "./even/even" +) + +func main() { + for i:=0; i<=100; i++ { + fmt.Printf("Is the integer %d even? %v\n", i, even.Even(i)) + } +} diff --git a/eBook/exercises/chapter_9/size_int.go b/eBook/exercises/chapter_9/size_int.go new file mode 100755 index 0000000..2fd9f88 --- /dev/null +++ b/eBook/exercises/chapter_9/size_int.go @@ -0,0 +1,14 @@ +// size_int.go +package main + +import ( + "fmt" + "unsafe" +) + +func main() { + var i int = 10 + size := unsafe.Sizeof(i) + fmt.Println("The size of an int is: ", size) +} +// The size of an int is: 4