From 2634a9ca4b60ca9f2882839f7f73ae803e3a1e9d Mon Sep 17 00:00:00 2001 From: badkaktus Date: Mon, 14 Oct 2019 11:38:21 +0300 Subject: [PATCH] first release --- examples/arrays/arrays.hash | 4 +- examples/atomic-counters/atomic-counters.hash | 4 +- examples/base64-encoding/base64-encoding.sh | 5 +- .../channel-buffering/channel-buffering.hash | 4 +- .../channel-directions.hash | 4 +- .../channel-synchronization.hash | 4 +- .../channel-synchronization.sh | 3 +- examples/channels/channels.hash | 4 +- .../closing-channels/closing-channels.hash | 4 +- examples/closures/closures.hash | 4 +- .../collection-functions.hash | 4 +- .../command-line-arguments.hash | 4 +- .../command-line-flags.hash | 4 +- .../command-line-subcommands.hash | 4 +- examples/constants/constants.hash | 4 +- examples/defer/defer.hash | 4 +- examples/directories/directories.hash | 4 +- .../environment-variables.hash | 4 +- examples/epoch/epoch.hash | 4 +- examples/errors/errors.hash | 4 +- .../execing-processes/execing-processes.hash | 4 +- examples/exit/exit.hash | 4 +- examples/file-paths/file-paths.hash | 4 +- examples/for/for.hash | 4 +- examples/functions/functions.hash | 4 +- examples/goroutines/goroutines.hash | 4 +- examples/hello-world/hello-world.hash | 4 +- examples/if-else/if-else.hash | 4 +- examples/interfaces/interfaces.hash | 4 +- examples/json/json.hash | 4 +- examples/line-filters/line-filters.hash | 4 +- examples/line-filters/line-filters.sh | 3 +- examples/maps/maps.hash | 4 +- examples/maps/maps.sh | 4 +- examples/methods/methods.hash | 4 +- .../multiple-return-values.hash | 4 +- examples/mutexes/mutexes.hash | 4 +- examples/mutexes/mutexes.sh | 6 +- .../non-blocking-channel-operations.hash | 4 +- examples/number-parsing/number-parsing.hash | 4 +- examples/panic/panic.hash | 4 +- examples/panic/panic.sh | 4 +- examples/pointers/pointers.hash | 4 +- examples/random-numbers/random-numbers.hash | 4 +- .../range-over-channels.hash | 4 +- examples/range/range.hash | 4 +- examples/rate-limiting/rate-limiting.hash | 4 +- examples/reading-files/reading-files.hash | 4 +- examples/recursion/recursion.hash | 4 +- .../regular-expressions.hash | 4 +- examples/select/select.hash | 4 +- examples/sha1-hashes/sha1-hashes.sh | 3 +- examples/signals/signals.hash | 4 +- examples/slices/slices.hash | 4 +- .../sorting-by-functions.hash | 4 +- examples/sorting/sorting.hash | 4 +- .../spawning-processes.hash | 4 +- .../stateful-goroutines.hash | 4 +- .../string-formatting/string-formatting.hash | 4 +- .../string-functions/string-functions.hash | 4 +- examples/structs/structs.hash | 4 +- examples/switch/switch.hash | 4 +- .../temporary-files-and-directories.hash | 4 +- examples/testing/testing.hash | 4 +- examples/tickers/tickers.hash | 4 +- examples/tickers/tickers.sh | 4 +- .../time-formatting-parsing.hash | 4 +- examples/time/time.hash | 4 +- examples/timeouts/timeouts.hash | 4 +- examples/timers/timers.hash | 4 +- examples/values/values.hash | 4 +- examples/variables/variables.hash | 4 +- .../variadic-functions.hash | 4 +- examples/waitgroups/waitgroups.hash | 4 +- examples/worker-pools/worker-pools.hash | 4 +- examples/writing-files/writing-files.hash | 4 +- examples/xml/xml.hash | 4 +- public/arrays | 180 +------- public/atomic-counters | 210 +-------- public/base64 | 41 ++ public/base64-encoding | 198 -------- public/channel-buffering | 127 +----- public/channel-directions | 119 +---- public/channel-synchronization | 158 +------ public/channels | 142 +----- public/closing-channels | 168 +------ public/closures | 164 +------ public/collection-functions | 345 +------------- public/command-line-arguments | 144 +----- public/command-line-flags | 284 +----------- public/command-line-subcommands | 237 +--------- public/constants | 157 +------ public/defer | 41 +- public/directories | 327 +------------ public/environment-variables | 162 +------ public/epoch | 35 +- public/errors | 273 +---------- public/execing-processes | 177 +------ public/exit | 150 +----- public/file-paths | 224 +-------- public/for | 169 +------ public/functions | 167 +------ public/goroutines | 181 +------- public/hello-world | 12 +- public/http | 41 ++ public/http-clients | 176 ------- public/http-servers | 217 --------- public/if-else | 26 +- public/index.html | 148 +++--- public/interfaces | 210 +-------- public/json | 107 ++--- public/line-filters | 178 +------- public/maps | 206 +-------- public/methods | 171 +------ public/multiple-return-values | 140 +----- public/mutexes | 271 +---------- public/non-blocking-channel-operations | 150 +----- public/number-parsing | 189 +------- public/panic | 46 +- public/pointers | 167 +------ public/random-numbers | 203 +-------- public/range | 174 +------ public/range-over-channels | 128 +----- public/rate-limiting | 235 +--------- public/reading-files | 263 +---------- public/recursion | 99 +--- public/regular-expressions | 316 +------------ public/select | 38 +- public/sha1 | 41 ++ public/sha1-hashes | 210 --------- public/signals | 162 +------ public/slices | 282 +----------- public/sorting | 134 +----- public/sorting-by-functions | 151 +----- public/spawning-processes | 235 +--------- public/stateful-goroutines | 286 +----------- public/string-formatting | 431 +----------------- public/string-functions | 183 +------- public/structs | 240 +--------- public/switch | 33 +- public/temporary-files-and-directories | 215 +-------- public/testing | 206 +-------- public/tickers | 145 +----- public/time | 244 +--------- public/time-formatting-parsing | 178 +------- public/timeouts | 155 +------ public/timers | 144 +----- public/url | 41 ++ public/url-parsing | 242 ---------- public/values | 126 +---- public/variables | 157 +------ public/variadic-functions | 146 +----- public/waitgroups | 39 +- public/worker-pools | 197 +------- public/writing-files | 261 +---------- public/xml | 48 +- templates/index.tmpl | 20 +- tools/generate.go | 9 +- 158 files changed, 869 insertions(+), 12891 deletions(-) create mode 100644 public/base64 delete mode 100644 public/base64-encoding create mode 100644 public/http delete mode 100644 public/http-clients delete mode 100644 public/http-servers create mode 100644 public/sha1 delete mode 100644 public/sha1-hashes create mode 100644 public/url delete mode 100644 public/url-parsing diff --git a/examples/arrays/arrays.hash b/examples/arrays/arrays.hash index cae0e0d..8ab57f4 100644 --- a/examples/arrays/arrays.hash +++ b/examples/arrays/arrays.hash @@ -1,2 +1,2 @@ -305975d13d24223181d13f042b290906d86c1a0e -W7NwfDq8Vdw +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/atomic-counters/atomic-counters.hash b/examples/atomic-counters/atomic-counters.hash index 989ed19..8ab57f4 100644 --- a/examples/atomic-counters/atomic-counters.hash +++ b/examples/atomic-counters/atomic-counters.hash @@ -1,2 +1,2 @@ -8ebec0be3b167021c96b8b497d0e8c0a2ea99385 -F2pJfduyQiA +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/base64-encoding/base64-encoding.sh b/examples/base64-encoding/base64-encoding.sh index dece8a5..48e4fab 100644 --- a/examples/base64-encoding/base64-encoding.sh +++ b/examples/base64-encoding/base64-encoding.sh @@ -1,6 +1,7 @@ # Строка кодируется в слегка отличающиеся значения с -# помощью стандартных и URL-совместимые base64 (`+` vs `-`), -# но они оба декодируются в исходную строку по желанию. +# помощью стандартных и URL-совместимые base64 +# (`+` vs `-`), но они оба декодируются в исходную +# строку по желанию. $ go run base64-encoding.go YWJjMTIzIT8kKiYoKSctPUB+ abc123!?$*&()'-=@~ diff --git a/examples/channel-buffering/channel-buffering.hash b/examples/channel-buffering/channel-buffering.hash index 6956e03..8ab57f4 100644 --- a/examples/channel-buffering/channel-buffering.hash +++ b/examples/channel-buffering/channel-buffering.hash @@ -1,2 +1,2 @@ -122140f7ad1bc5cff4fcd7a9e7245b87aaca3ec5 -mPoF-Xi-rip +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/channel-directions/channel-directions.hash b/examples/channel-directions/channel-directions.hash index fb68662..8ab57f4 100644 --- a/examples/channel-directions/channel-directions.hash +++ b/examples/channel-directions/channel-directions.hash @@ -1,2 +1,2 @@ -635cc13dfe33123ac188e01e3002d3aa935d765f -Jnn9_9hC48c +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/channel-synchronization/channel-synchronization.hash b/examples/channel-synchronization/channel-synchronization.hash index 9dea9a0..8ab57f4 100644 --- a/examples/channel-synchronization/channel-synchronization.hash +++ b/examples/channel-synchronization/channel-synchronization.hash @@ -1,2 +1,2 @@ -0d5a9de912e2a4a18943e082e2f8107cb75d0ce4 -fe9If6OhYMk +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/channel-synchronization/channel-synchronization.sh b/examples/channel-synchronization/channel-synchronization.sh index e6a6226..dc71693 100644 --- a/examples/channel-synchronization/channel-synchronization.sh +++ b/examples/channel-synchronization/channel-synchronization.sh @@ -2,4 +2,5 @@ $ go run channel-synchronization.go working...done # Если вы удалите строку `<- done` из этой программы, -# программа закроется до того, как `воркер` даже запустится. +# программа закроется до того, как `воркер` даже +# запустится. diff --git a/examples/channels/channels.hash b/examples/channels/channels.hash index 92301ce..8ab57f4 100644 --- a/examples/channels/channels.hash +++ b/examples/channels/channels.hash @@ -1,2 +1,2 @@ -926212c784ab820648906c96f6ab21afbc161526 -bRGMAqinovA +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/closing-channels/closing-channels.hash b/examples/closing-channels/closing-channels.hash index 007751f..8ab57f4 100644 --- a/examples/closing-channels/closing-channels.hash +++ b/examples/closing-channels/closing-channels.hash @@ -1,2 +1,2 @@ -5205898a520533e46ea24c849848d19ebc2d08a9 -mkz69rVMHs6 +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/closures/closures.hash b/examples/closures/closures.hash index fa66f0f..8ab57f4 100644 --- a/examples/closures/closures.hash +++ b/examples/closures/closures.hash @@ -1,2 +1,2 @@ -e304df67e760dda93ffe434aca58aea4a6c94f19 -zb93qzV6iN3 +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/collection-functions/collection-functions.hash b/examples/collection-functions/collection-functions.hash index abbd3d5..8ab57f4 100644 --- a/examples/collection-functions/collection-functions.hash +++ b/examples/collection-functions/collection-functions.hash @@ -1,2 +1,2 @@ -28456737ea996664bdaeb8e1e821d95697d00646 -8hI6oPNEfyh +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/command-line-arguments/command-line-arguments.hash b/examples/command-line-arguments/command-line-arguments.hash index ad22b59..8ab57f4 100644 --- a/examples/command-line-arguments/command-line-arguments.hash +++ b/examples/command-line-arguments/command-line-arguments.hash @@ -1,2 +1,2 @@ -9c80d495201148bbeb0fd0a5a2ce1735aeb34b60 -myJy_-H8Fo_Q +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/command-line-flags/command-line-flags.hash b/examples/command-line-flags/command-line-flags.hash index abee236..8ab57f4 100644 --- a/examples/command-line-flags/command-line-flags.hash +++ b/examples/command-line-flags/command-line-flags.hash @@ -1,2 +1,2 @@ -ab08bf890dcd87b807956b5bee441d59efe458e3 -lPaZodnG9TF +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/command-line-subcommands/command-line-subcommands.hash b/examples/command-line-subcommands/command-line-subcommands.hash index f22bcc8..8ab57f4 100644 --- a/examples/command-line-subcommands/command-line-subcommands.hash +++ b/examples/command-line-subcommands/command-line-subcommands.hash @@ -1,2 +1,2 @@ -5a0ec258e4992e9b93b11d48f2f249092ff3db66 -gtgSAg76N4I +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/constants/constants.hash b/examples/constants/constants.hash index 93d42ca..8ab57f4 100644 --- a/examples/constants/constants.hash +++ b/examples/constants/constants.hash @@ -1,2 +1,2 @@ -7cc09460e8dc6fffd0ba811679f92a85eb51e927 -gmjHSglwLic +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/defer/defer.hash b/examples/defer/defer.hash index d45bfd7..f0d0098 100644 --- a/examples/defer/defer.hash +++ b/examples/defer/defer.hash @@ -1,2 +1,2 @@ -4fc23579a9bd5d8512884902394f4dce51eb7d60 -QJJ2R6kv6K5 +e5ed44b5c1d834858b5f5ad5a09d3b699685ede4 +lVhFAPGaGby diff --git a/examples/directories/directories.hash b/examples/directories/directories.hash index cebae56..8ab57f4 100644 --- a/examples/directories/directories.hash +++ b/examples/directories/directories.hash @@ -1,2 +1,2 @@ -83f67db91816b4544072d0a4d099111a21c60723 --7kWq0PmATF +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/environment-variables/environment-variables.hash b/examples/environment-variables/environment-variables.hash index b245851..8ab57f4 100644 --- a/examples/environment-variables/environment-variables.hash +++ b/examples/environment-variables/environment-variables.hash @@ -1,2 +1,2 @@ -db2e203da519a22943753295e9cc27d89e4347b0 -bKuCOOD16KH +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/epoch/epoch.hash b/examples/epoch/epoch.hash index d37c230..8a10285 100644 --- a/examples/epoch/epoch.hash +++ b/examples/epoch/epoch.hash @@ -1,2 +1,2 @@ -184c8f3e94dd28176be81956115ac417e33513a6 -3uYNHHRplmQ +ff3aa7643a7a315f15f4de39770e3105907c8300 +MdrFxlv7Ds8 diff --git a/examples/errors/errors.hash b/examples/errors/errors.hash index b650d25..8ab57f4 100644 --- a/examples/errors/errors.hash +++ b/examples/errors/errors.hash @@ -1,2 +1,2 @@ -ed58ad3162d93c723d3efe72529a61ce7041fe13 -vrwN32gxaYx +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/execing-processes/execing-processes.hash b/examples/execing-processes/execing-processes.hash index 020f78e..8ab57f4 100644 --- a/examples/execing-processes/execing-processes.hash +++ b/examples/execing-processes/execing-processes.hash @@ -1,2 +1,2 @@ -e6b4830d4264f307506b54726ec79b25a0363874 -ahZjpJaZz44 +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/exit/exit.hash b/examples/exit/exit.hash index 234717b..8ab57f4 100644 --- a/examples/exit/exit.hash +++ b/examples/exit/exit.hash @@ -1,2 +1,2 @@ -2316e6c8e364e2066c6bd350dc9b0b2af85b63fe -OX997ykuOGx +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/file-paths/file-paths.hash b/examples/file-paths/file-paths.hash index f1610a1..8ab57f4 100644 --- a/examples/file-paths/file-paths.hash +++ b/examples/file-paths/file-paths.hash @@ -1,2 +1,2 @@ -1215302b9e59ee9dee21dcd3c47d5f6c672fb058 -QIitbMNiFRx +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/for/for.hash b/examples/for/for.hash index 7852dec..8ab57f4 100644 --- a/examples/for/for.hash +++ b/examples/for/for.hash @@ -1,2 +1,2 @@ -33056d6b36f9894fb6359c9cf2ef8725bbdafa19 -lGYfUJwiGfi +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/functions/functions.hash b/examples/functions/functions.hash index 85d4e8f..8ab57f4 100644 --- a/examples/functions/functions.hash +++ b/examples/functions/functions.hash @@ -1,2 +1,2 @@ -ae669923c20e5ebf4a7b4b11b8fdf2972accf9e2 -hzGUvK6iJNm +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/goroutines/goroutines.hash b/examples/goroutines/goroutines.hash index a83b7b8..8ab57f4 100644 --- a/examples/goroutines/goroutines.hash +++ b/examples/goroutines/goroutines.hash @@ -1,2 +1,2 @@ -3737e7b5129b649d202e75225a1ac732eda116d0 -rovAFf9-n78 +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/hello-world/hello-world.hash b/examples/hello-world/hello-world.hash index df7b0e0..fb17378 100644 --- a/examples/hello-world/hello-world.hash +++ b/examples/hello-world/hello-world.hash @@ -1,2 +1,2 @@ -c98395a44701add5bf84e2f3a63e300fc1bc4bfe -mp1ENMU6ZYu +0cbab39cbb8edefa4dcf19e15941e2222c14e7e6 +r-UD-XLVae8 diff --git a/examples/if-else/if-else.hash b/examples/if-else/if-else.hash index 844700f..629db32 100644 --- a/examples/if-else/if-else.hash +++ b/examples/if-else/if-else.hash @@ -1,2 +1,2 @@ -89b78f3378e1a574ddfd0260a0404a962852eff8 -p6-WKTqEks4 +c0056f359b48d1289414955203f5746ed1da7dd2 +DprUWlg26IL diff --git a/examples/interfaces/interfaces.hash b/examples/interfaces/interfaces.hash index b6fa983..8ab57f4 100644 --- a/examples/interfaces/interfaces.hash +++ b/examples/interfaces/interfaces.hash @@ -1,2 +1,2 @@ -aac1328f5a04568272b82753ff0762b9eacff4fc -hXTlbUAGcvn +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/json/json.hash b/examples/json/json.hash index 8c217d6..5da3b70 100644 --- a/examples/json/json.hash +++ b/examples/json/json.hash @@ -1,2 +1,2 @@ -c751bc7223b8bc615f82fe7643ab98ce2b80240f -ROikmz5tRhZ +cabda206e7e0a15d45b7460b6f5ec6df961809eb +Lky4Hyyl2-t diff --git a/examples/line-filters/line-filters.hash b/examples/line-filters/line-filters.hash index d62fbff..8ab57f4 100644 --- a/examples/line-filters/line-filters.hash +++ b/examples/line-filters/line-filters.hash @@ -1,2 +1,2 @@ -87f4a67edf741979f8ff6da85947aa177547f9ef -hnaOIaQAjKF +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/line-filters/line-filters.sh b/examples/line-filters/line-filters.sh index fecb350..2de2318 100644 --- a/examples/line-filters/line-filters.sh +++ b/examples/line-filters/line-filters.sh @@ -3,7 +3,8 @@ $ echo 'hello' > /tmp/lines $ echo 'filter' >> /tmp/lines -# Затем используйте фильтр строк, чтобы получить строчные буквы. +# Затем используйте фильтр строк, чтобы получить строчные +# буквы. $ cat /tmp/lines | go run line-filters.go HELLO FILTER diff --git a/examples/maps/maps.hash b/examples/maps/maps.hash index 57c1a72..8ab57f4 100644 --- a/examples/maps/maps.hash +++ b/examples/maps/maps.hash @@ -1,2 +1,2 @@ -3e39d07e3f80ecbac558c6fb8baee2a5f914cf97 -U67R66Oab8r +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/maps/maps.sh b/examples/maps/maps.sh index 2ac06d6..a1ce9d0 100644 --- a/examples/maps/maps.sh +++ b/examples/maps/maps.sh @@ -1,5 +1,5 @@ -# Обратите внимание, что карты отображаются в виде `map[k:v k:v]` -# при печати с помощью `fmt.Println` +# Обратите внимание, что карты отображаются в виде +# `map[k:v k:v]`при печати с помощью `fmt.Println` $ go run maps.go map: map[k1:7 k2:13] v1: 7 diff --git a/examples/methods/methods.hash b/examples/methods/methods.hash index 00c7c28..8ab57f4 100644 --- a/examples/methods/methods.hash +++ b/examples/methods/methods.hash @@ -1,2 +1,2 @@ -24cfb9ad45e43c2d49163149bc55925a4e1b3c7a -ffMb0txGnYB +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/multiple-return-values/multiple-return-values.hash b/examples/multiple-return-values/multiple-return-values.hash index 73f9fa8..8ab57f4 100644 --- a/examples/multiple-return-values/multiple-return-values.hash +++ b/examples/multiple-return-values/multiple-return-values.hash @@ -1,2 +1,2 @@ -5063ce3d3c70c6bd70f4b709de24bb93d0f24e0c -FZoIB5LXQGZ +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/mutexes/mutexes.hash b/examples/mutexes/mutexes.hash index aea2025..8ab57f4 100644 --- a/examples/mutexes/mutexes.hash +++ b/examples/mutexes/mutexes.hash @@ -1,2 +1,2 @@ -ca257d9594a6219d5803193132e999a32dc8c856 -IRewFKz2OPN +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/mutexes/mutexes.sh b/examples/mutexes/mutexes.sh index 6b243f9..83760b2 100644 --- a/examples/mutexes/mutexes.sh +++ b/examples/mutexes/mutexes.sh @@ -1,6 +1,6 @@ -# Запуск программы показывает, что мы выполнили около 90000 -# операций в нашем синхронизированном с `мьютексом` -# состоянии. +# Запуск программы показывает, что мы выполнили +# около 90000 операций в нашем синхронизированном +# с `мьютексом`состоянии. $ go run mutexes.go readOps: 83285 writeOps: 8320 diff --git a/examples/non-blocking-channel-operations/non-blocking-channel-operations.hash b/examples/non-blocking-channel-operations/non-blocking-channel-operations.hash index a9f03de..8ab57f4 100644 --- a/examples/non-blocking-channel-operations/non-blocking-channel-operations.hash +++ b/examples/non-blocking-channel-operations/non-blocking-channel-operations.hash @@ -1,2 +1,2 @@ -a6e0a8bb87153c7ed0de4996172f7ad5d89c6814 -n5ttmOsMrrJ +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/number-parsing/number-parsing.hash b/examples/number-parsing/number-parsing.hash index eeaf3cd..8ab57f4 100644 --- a/examples/number-parsing/number-parsing.hash +++ b/examples/number-parsing/number-parsing.hash @@ -1,2 +1,2 @@ -0191c7e43706640207c403ba92dd2272d66fc868 -t2q4KnWWTAw +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/panic/panic.hash b/examples/panic/panic.hash index bd32ff3..1ada902 100644 --- a/examples/panic/panic.hash +++ b/examples/panic/panic.hash @@ -1,2 +1,2 @@ -91639bbcfcc6ed088295a9ee6b1c36ab35ae402a -91HXbZZZopt +b850cd4c8507129c13f1c12662f107bc7b99a8f6 +eeoucVUhT6i diff --git a/examples/panic/panic.sh b/examples/panic/panic.sh index 0b311b0..82fc3fa 100644 --- a/examples/panic/panic.sh +++ b/examples/panic/panic.sh @@ -12,5 +12,5 @@ exit status 2 # Обратите внимание, что в отличие от некоторых языков, # которые используют исключения для обработки -# ошибок, в Go привычно использовать возвращающие значения, -# указывающие на ошибки. \ No newline at end of file +# ошибок, в Go привычно использовать возвращающие +# значения, указывающие на ошибки. \ No newline at end of file diff --git a/examples/pointers/pointers.hash b/examples/pointers/pointers.hash index a0c5985..8ab57f4 100644 --- a/examples/pointers/pointers.hash +++ b/examples/pointers/pointers.hash @@ -1,2 +1,2 @@ -85cff3345d2f22b65a5d54eb8f7aa8f508f27887 -fnQkHp4hriG +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/random-numbers/random-numbers.hash b/examples/random-numbers/random-numbers.hash index 3ebbc4a..8ab57f4 100644 --- a/examples/random-numbers/random-numbers.hash +++ b/examples/random-numbers/random-numbers.hash @@ -1,2 +1,2 @@ -9374869a809d28ea784a9e1181b4aa1988018776 -DVHO7SjJZnp +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/range-over-channels/range-over-channels.hash b/examples/range-over-channels/range-over-channels.hash index f0ffe62..8ab57f4 100644 --- a/examples/range-over-channels/range-over-channels.hash +++ b/examples/range-over-channels/range-over-channels.hash @@ -1,2 +1,2 @@ -8b5d8a77e84c34771c5b14af014ecef3f88b2a6c -QnARPm-ddFB +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/range/range.hash b/examples/range/range.hash index 2f8d0da..8ab57f4 100644 --- a/examples/range/range.hash +++ b/examples/range/range.hash @@ -1,2 +1,2 @@ -ebe328a57f3d34708709ca99d3304af1733592d9 -JTY1VAUjfBw +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/rate-limiting/rate-limiting.hash b/examples/rate-limiting/rate-limiting.hash index be48802..8ab57f4 100644 --- a/examples/rate-limiting/rate-limiting.hash +++ b/examples/rate-limiting/rate-limiting.hash @@ -1,2 +1,2 @@ -357d83df3e48675eb1e135188cb9f07448c1f146 -AJ-MJephNib +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/reading-files/reading-files.hash b/examples/reading-files/reading-files.hash index 8cf5bf6..8ab57f4 100644 --- a/examples/reading-files/reading-files.hash +++ b/examples/reading-files/reading-files.hash @@ -1,2 +1,2 @@ -463a6f2999a023887af6b23c8f79f24978eb8115 -cocJ6kBH_iZ +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/recursion/recursion.hash b/examples/recursion/recursion.hash index 2ebf561..8ab57f4 100644 --- a/examples/recursion/recursion.hash +++ b/examples/recursion/recursion.hash @@ -1,2 +1,2 @@ -5d1ba6b03a50ccae2a0f46865eb72c587e11857c -4yUp5wLVyiG +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/regular-expressions/regular-expressions.hash b/examples/regular-expressions/regular-expressions.hash index 236706c..8ab57f4 100644 --- a/examples/regular-expressions/regular-expressions.hash +++ b/examples/regular-expressions/regular-expressions.hash @@ -1,2 +1,2 @@ -de24265897edf1d3913e3b87f70757284a66ecea -urHlUNDVenk +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/select/select.hash b/examples/select/select.hash index ea97b26..e3b7f8a 100644 --- a/examples/select/select.hash +++ b/examples/select/select.hash @@ -1,2 +1,2 @@ -6e1125087bc036ebd905452300575f160d683918 -yF-xgN7Xf9P +04c7b3aa9c1b7b90a70f9853719fa97af74dfb3d +S6N4SGilqad diff --git a/examples/sha1-hashes/sha1-hashes.sh b/examples/sha1-hashes/sha1-hashes.sh index 9e4c8b0..1a69c92 100644 --- a/examples/sha1-hashes/sha1-hashes.sh +++ b/examples/sha1-hashes/sha1-hashes.sh @@ -6,7 +6,8 @@ cf23df2207d99a74fbe169e3eba035e633b65d94 # Вы можете вычислить другие хэши, используя шаблон, # аналогичный показанному выше. Например, для вычисления -# хэшей MD5 импортируйте `crypto/md5` и используйте `md5.New()`. +# хэшей MD5 импортируйте `crypto/md5` и используйте +# `md5.New()`. # Обратите внимание, что если вам нужны криптографически # защищенные хэши, вы должны тщательно исследовать diff --git a/examples/signals/signals.hash b/examples/signals/signals.hash index 82345ca..8ab57f4 100644 --- a/examples/signals/signals.hash +++ b/examples/signals/signals.hash @@ -1,2 +1,2 @@ -1e43c6f63f1d57e1a52c89f52d35b68757e9676b -_6oj-T3Gko2 +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/slices/slices.hash b/examples/slices/slices.hash index 8b501cb..8ab57f4 100644 --- a/examples/slices/slices.hash +++ b/examples/slices/slices.hash @@ -1,2 +1,2 @@ -c6fa1627841f199dbf901f88580cb97eb92c5530 -Z3_U32sn8RF +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/sorting-by-functions/sorting-by-functions.hash b/examples/sorting-by-functions/sorting-by-functions.hash index d62f035..8ab57f4 100644 --- a/examples/sorting-by-functions/sorting-by-functions.hash +++ b/examples/sorting-by-functions/sorting-by-functions.hash @@ -1,2 +1,2 @@ -f7d0b7840dd12601fb86946f9dc4c38fb1c0501f -Jtxf94x94Hx +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/sorting/sorting.hash b/examples/sorting/sorting.hash index d72396f..8ab57f4 100644 --- a/examples/sorting/sorting.hash +++ b/examples/sorting/sorting.hash @@ -1,2 +1,2 @@ -e11e944d34b21e75ce4f7c91026d4200ce592dc5 -tAWAkRlBJNX +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/spawning-processes/spawning-processes.hash b/examples/spawning-processes/spawning-processes.hash index bcde707..8ab57f4 100644 --- a/examples/spawning-processes/spawning-processes.hash +++ b/examples/spawning-processes/spawning-processes.hash @@ -1,2 +1,2 @@ -cc68e4290f10209ad2fa8db74fdfaea7fdb44d5c -QS_Nkoe8VLG +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/stateful-goroutines/stateful-goroutines.hash b/examples/stateful-goroutines/stateful-goroutines.hash index 1f3eb48..8ab57f4 100644 --- a/examples/stateful-goroutines/stateful-goroutines.hash +++ b/examples/stateful-goroutines/stateful-goroutines.hash @@ -1,2 +1,2 @@ -956afe7524b492b2e85f8320c70f180c448a764a -saQTLpdIgp2 +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/string-formatting/string-formatting.hash b/examples/string-formatting/string-formatting.hash index c339d9b..8ab57f4 100644 --- a/examples/string-formatting/string-formatting.hash +++ b/examples/string-formatting/string-formatting.hash @@ -1,2 +1,2 @@ -12b245c576b43537c092a5b84995ebca8ce78a57 -vmYSdxfUcRh +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/string-functions/string-functions.hash b/examples/string-functions/string-functions.hash index 568c7c6..8ab57f4 100644 --- a/examples/string-functions/string-functions.hash +++ b/examples/string-functions/string-functions.hash @@ -1,2 +1,2 @@ -bf39c7540bd78eba38eb5a9047a9d0ffc7235f85 -xoRUhG86wsF +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/structs/structs.hash b/examples/structs/structs.hash index 15fcdc0..8ab57f4 100644 --- a/examples/structs/structs.hash +++ b/examples/structs/structs.hash @@ -1,2 +1,2 @@ -c5caaf1eefaf084d688afb70d2ee5884a4983182 -00Yiw6xuICq +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/switch/switch.hash b/examples/switch/switch.hash index 54d2e9f..aabab4a 100644 --- a/examples/switch/switch.hash +++ b/examples/switch/switch.hash @@ -1,2 +1,2 @@ -2486fc553301cdeac9a26f3d0b3aed4143d9f4f0 -ZcDzdx3nYQn +54def01d02fd9f42dc61d404994c892d97151826 +wb2tCpSAqzw diff --git a/examples/temporary-files-and-directories/temporary-files-and-directories.hash b/examples/temporary-files-and-directories/temporary-files-and-directories.hash index f523002..8ab57f4 100644 --- a/examples/temporary-files-and-directories/temporary-files-and-directories.hash +++ b/examples/temporary-files-and-directories/temporary-files-and-directories.hash @@ -1,2 +1,2 @@ -5f7d0c43988d7dce235adb06ec02f4d2026b7f83 -pxE20wGTFjv +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/testing/testing.hash b/examples/testing/testing.hash index 317487f..8ab57f4 100644 --- a/examples/testing/testing.hash +++ b/examples/testing/testing.hash @@ -1,2 +1,2 @@ -8f00c5178a33be2e92a853f14bfc3fbf0919cd97 -fyy7h1adGWr +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/tickers/tickers.hash b/examples/tickers/tickers.hash index e724ec1..8ab57f4 100644 --- a/examples/tickers/tickers.hash +++ b/examples/tickers/tickers.hash @@ -1,2 +1,2 @@ -4a42333d14f902e890902343c7bd9b9c735fd8ad -n1q1sSGEvmv +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/tickers/tickers.sh b/examples/tickers/tickers.sh index 29722b8..c3f50a1 100644 --- a/examples/tickers/tickers.sh +++ b/examples/tickers/tickers.sh @@ -1,5 +1,5 @@ -# Когда мы запускаем эту программу, тикер должен выполнится -# 3 раза, после чего остановиться. +# Когда мы запускаем эту программу, тикер должен +# выполнится 3 раза, после чего остановиться. $ go run tickers.go Tick at 2012-09-23 11:29:56.487625 -0700 PDT Tick at 2012-09-23 11:29:56.988063 -0700 PDT diff --git a/examples/time-formatting-parsing/time-formatting-parsing.hash b/examples/time-formatting-parsing/time-formatting-parsing.hash index eee6d65..8ab57f4 100644 --- a/examples/time-formatting-parsing/time-formatting-parsing.hash +++ b/examples/time-formatting-parsing/time-formatting-parsing.hash @@ -1,2 +1,2 @@ -9e3f17061fef280191e3e8518365e231e17a5d5a -1410R7Fcyx0 +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/time/time.hash b/examples/time/time.hash index 2c9d415..8ab57f4 100644 --- a/examples/time/time.hash +++ b/examples/time/time.hash @@ -1,2 +1,2 @@ -c47d853fa7527a652ce78b0285e452c6cd740050 -u-7i_p8BHVt +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/timeouts/timeouts.hash b/examples/timeouts/timeouts.hash index f622aeb..8ab57f4 100644 --- a/examples/timeouts/timeouts.hash +++ b/examples/timeouts/timeouts.hash @@ -1,2 +1,2 @@ -b8d3e745539b24d3530ca21efcdc924f08769edb -TYJgoFjlTd6 +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/timers/timers.hash b/examples/timers/timers.hash index 8c0f2c4..8ab57f4 100644 --- a/examples/timers/timers.hash +++ b/examples/timers/timers.hash @@ -1,2 +1,2 @@ -e8e501d6083bea786629ca5e485e8b18caab4815 -pLnKEIesooU +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/values/values.hash b/examples/values/values.hash index b10176b..8ab57f4 100644 --- a/examples/values/values.hash +++ b/examples/values/values.hash @@ -1,2 +1,2 @@ -c5a53c75cc57dc15ac4458285c9b139bf85c67bf -aGiVohrYqYC +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/variables/variables.hash b/examples/variables/variables.hash index 316281a..8ab57f4 100644 --- a/examples/variables/variables.hash +++ b/examples/variables/variables.hash @@ -1,2 +1,2 @@ -636a63e1bf810cb9d0620cc5160330f6d3d8679d -kwm2xuWnlKq +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/variadic-functions/variadic-functions.hash b/examples/variadic-functions/variadic-functions.hash index 3c44a2b..8ab57f4 100644 --- a/examples/variadic-functions/variadic-functions.hash +++ b/examples/variadic-functions/variadic-functions.hash @@ -1,2 +1,2 @@ -34ba16069a5d972a837cc5c0172ab30873535220 -7f0JlVhToDD +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/waitgroups/waitgroups.hash b/examples/waitgroups/waitgroups.hash index 71ecfc8..127b5e6 100644 --- a/examples/waitgroups/waitgroups.hash +++ b/examples/waitgroups/waitgroups.hash @@ -1,2 +1,2 @@ -499c7ee59b2ae06d2d3171768d9cf11762121a87 -gLLmgcR7YkP +e2776c97c7388b32808049205e557be97f74fb9c +NiNMDeuci4O diff --git a/examples/worker-pools/worker-pools.hash b/examples/worker-pools/worker-pools.hash index dbfeb88..8ab57f4 100644 --- a/examples/worker-pools/worker-pools.hash +++ b/examples/worker-pools/worker-pools.hash @@ -1,2 +1,2 @@ -9b30cdfc3f46d634c3b8671a7ae1551c133fb6e2 -IiKZ-nj-nKY +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/writing-files/writing-files.hash b/examples/writing-files/writing-files.hash index 360897a..8ab57f4 100644 --- a/examples/writing-files/writing-files.hash +++ b/examples/writing-files/writing-files.hash @@ -1,2 +1,2 @@ -0853ca57176872e9b34b501855ceb8bf5fbdbf46 -gyJn9PcndtP +da39a3ee5e6b4b0d3255bfef95601890afd80709 +UCPdVNrl0-P diff --git a/examples/xml/xml.hash b/examples/xml/xml.hash index 104125d..91fb9a6 100644 --- a/examples/xml/xml.hash +++ b/examples/xml/xml.hash @@ -1,2 +1,2 @@ -18ada773098bca38778a58b438d6af70529f18b0 -qd9Ii_3AW0s +dcb799997023b0aa184fefbc443c6f5c7608334f +LICUcN7BbAV diff --git a/public/arrays b/public/arrays index d8273e0..d19bf1c 100644 --- a/public/arrays +++ b/public/arrays @@ -2,7 +2,7 @@ - Go by Example: Arrays + Go в примерах: Массивы (Arrays)
-

Go by Example: Arrays

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

In Go, an array is a numbered sequence of elements of a -specific length.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

Here we create an array a that will hold exactly -5 ints. The type of elements and length are both -part of the array’s type. By default an array is -zero-valued, which for ints means 0s.

- -
- -
    var a [5]int
-    fmt.Println("emp:", a)
-
- -
-

We can set a value at an index using the -array[index] = value syntax, and get a value with -array[index].

- -
- -
    a[4] = 100
-    fmt.Println("set:", a)
-    fmt.Println("get:", a[4])
-
- -
-

The builtin len returns the length of an array.

- -
- -
    fmt.Println("len:", len(a))
-
- -
-

Use this syntax to declare and initialize an array -in one line.

- -
- -
    b := [5]int{1, 2, 3, 4, 5}
-    fmt.Println("dcl:", b)
-
- -
-

Array types are one-dimensional, but you can -compose types to build multi-dimensional data -structures.

- -
- -
    var twoD [2][3]int
-    for i := 0; i < 2; i++ {
-        for j := 0; j < 3; j++ {
-            twoD[i][j] = i + j
-        }
-    }
-    fmt.Println("2d: ", twoD)
-}
-
- -
- - - - - - - - - - - - - -
-

Note that arrays appear in the form [v1 v2 v3 ...] -when printed with fmt.Println.

- -
- -
$ go run arrays.go
-emp: [0 0 0 0 0]
-set: [0 0 0 0 100]
-get: 100
-len: 5
-dcl: [1 2 3 4 5]
-2d:  [[0 1 2] [1 2 3]]
-
- -
-

You’ll see slices much more often than arrays in -typical Go. We’ll look at slices next.

- -
- - -
+

Go в примерах: Массивы (Arrays)

- Next example: Slices. + Следующий пример: Срезы (Slices).

diff --git a/public/atomic-counters b/public/atomic-counters index 9627c97..e073b4b 100644 --- a/public/atomic-counters +++ b/public/atomic-counters @@ -2,7 +2,7 @@ - Go by Example: Atomic Counters + Go в примерах: Атомарные счетчики (Atomic Counters)
-

Go by Example: Atomic Counters

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

The primary mechanism for managing state in Go is -communication over channels. We saw this for example -with worker pools. There are a few other -options for managing state though. Here we’ll -look at using the sync/atomic package for atomic -counters accessed by multiple goroutines.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "sync"
-    "sync/atomic"
-)
-
- -
- - - -
func main() {
-
- -
-

We’ll use an unsigned integer to represent our -(always-positive) counter.

- -
- -
    var ops uint64
-
- -
-

A WaitGroup will help us wait for all goroutines -to finish their work.

- -
- -
    var wg sync.WaitGroup
-
- -
-

We’ll start 50 goroutines that each increment the -counter exactly 1000 times.

- -
- -
    for i := 0; i < 50; i++ {
-        wg.Add(1)
-
- -
-

To atomically increment the counter we -use AddUint64, giving it the memory -address of our ops counter with the -& syntax.

- -
- -
        go func() {
-            for c := 0; c < 1000; c++ {
-
- -
- - - -
                atomic.AddUint64(&ops, 1)
-            }
-            wg.Done()
-        }()
-    }
-
- -
-

Wait until all the goroutines are done.

- -
- -
    wg.Wait()
-
- -
-

It’s safe to access ops now because we know -no other goroutine is writing to it. Reading -atomics safely while they are being updated is -also possible, using functions like -atomic.LoadUint64.

- -
- -
    fmt.Println("ops:", ops)
-}
-
- -
- - - - - - - - - - - - - -
-

We expect to get exactly 50,000 operations. Had we -used the non-atomic ops++ to increment the counter, -we’d likely get a different number, changing between -runs, because the goroutines would interfere with -each other. Moreover, we’d get data race failures -when running with the -race flag.

- -
- -
$ go run atomic-counters.go
-ops: 50000
-
- -
-

Next we’ll look at mutexes, another tool for managing -state.

- -
- - -
+

Go в примерах: Атомарные счетчики (Atomic Counters)

- Next example: Mutexes. + Следующий пример: Мьютексы (Mutexes).

diff --git a/public/base64 b/public/base64 new file mode 100644 index 0000000..eadbd1c --- /dev/null +++ b/public/base64 @@ -0,0 +1,41 @@ + + + + + Go в примерах: Кодирование Base64 (Base64 Encoding) + + + + +
+

Go в примерах: Кодирование Base64 (Base64 Encoding)

+ + +

+ Следующий пример: Чтение файлов (Reading Files). +

+ + +
+ + + + diff --git a/public/base64-encoding b/public/base64-encoding deleted file mode 100644 index 7bf8d28..0000000 --- a/public/base64-encoding +++ /dev/null @@ -1,198 +0,0 @@ - - - - - Go by Example: Base64 Encoding - - - - -
-

Go by Example: Base64 Encoding

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go provides built-in support for base64 -encoding/decoding.

- -
- - -
- - - -
package main
-
- -
-

This syntax imports the encoding/base64 package with -the b64 name instead of the default base64. It’ll -save us some space below.

- -
- -
import (
-    b64 "encoding/base64"
-    "fmt"
-)
-
- -
- - - -
func main() {
-
- -
-

Here’s the string we’ll encode/decode.

- -
- -
    data := "abc123!?$*&()'-=@~"
-
- -
-

Go supports both standard and URL-compatible -base64. Here’s how to encode using the standard -encoder. The encoder requires a []byte so we -convert our string to that type.

- -
- -
    sEnc := b64.StdEncoding.EncodeToString([]byte(data))
-    fmt.Println(sEnc)
-
- -
-

Decoding may return an error, which you can check -if you don’t already know the input to be -well-formed.

- -
- -
    sDec, _ := b64.StdEncoding.DecodeString(sEnc)
-    fmt.Println(string(sDec))
-    fmt.Println()
-
- -
-

This encodes/decodes using a URL-compatible base64 -format.

- -
- -
    uEnc := b64.URLEncoding.EncodeToString([]byte(data))
-    fmt.Println(uEnc)
-    uDec, _ := b64.URLEncoding.DecodeString(uEnc)
-    fmt.Println(string(uDec))
-}
-
- -
- - - - - - - - - - - - - -
-

The string encodes to slightly different values with the -standard and URL base64 encoders (trailing + vs -) -but they both decode to the original string as desired.

- -
- -
$ go run base64-encoding.go
-YWJjMTIzIT8kKiYoKSctPUB+
-abc123!?$*&()'-=@~
-
- -
- - - -
YWJjMTIzIT8kKiYoKSctPUB-
-abc123!?$*&()'-=@~
-
- -
- - -

- Next example: Reading Files. -

- - -
- - - - diff --git a/public/channel-buffering b/public/channel-buffering index eab9a6e..36fd138 100644 --- a/public/channel-buffering +++ b/public/channel-buffering @@ -2,7 +2,7 @@ - Go by Example: Channel Buffering + Go в примерах: Буферизированный канал (Channel Buffering)
-

Go by Example: Channel Buffering

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

By default channels are unbuffered, meaning that they -will only accept sends (chan <-) if there is a -corresponding receive (<- chan) ready to receive the -sent value. Buffered channels accept a limited -number of values without a corresponding receiver for -those values.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

Here we make a channel of strings buffering up to -2 values.

- -
- -
    messages := make(chan string, 2)
-
- -
-

Because this channel is buffered, we can send these -values into the channel without a corresponding -concurrent receive.

- -
- -
    messages <- "buffered"
-    messages <- "channel"
-
- -
-

Later we can receive these two values as usual.

- -
- -
    fmt.Println(<-messages)
-    fmt.Println(<-messages)
-}
-
- -
- - - - - - - - -
- - - -
$ go run channel-buffering.go 
-buffered
-channel
-
- -
+

Go в примерах: Буферизированный канал (Channel Buffering)

- Next example: Channel Synchronization. + Следующий пример: Синхронизация канала (Channel Synchronization).

diff --git a/public/channel-directions b/public/channel-directions index fbbe7b5..f50b677 100644 --- a/public/channel-directions +++ b/public/channel-directions @@ -2,7 +2,7 @@ - Go by Example: Channel Directions + Go в примерах: Направления канала (Channel Directions)
-

Go by Example: Channel Directions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

When using channels as function parameters, you can -specify if a channel is meant to only send or receive -values. This specificity increases the type-safety of -the program.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

This ping function only accepts a channel for sending -values. It would be a compile-time error to try to -receive on this channel.

- -
- -
func ping(pings chan<- string, msg string) {
-    pings <- msg
-}
-
- -
-

The pong function accepts one channel for receives -(pings) and a second for sends (pongs).

- -
- -
func pong(pings <-chan string, pongs chan<- string) {
-    msg := <-pings
-    pongs <- msg
-}
-
- -
- - - -
func main() {
-    pings := make(chan string, 1)
-    pongs := make(chan string, 1)
-    ping(pings, "passed message")
-    pong(pings, pongs)
-    fmt.Println(<-pongs)
-}
-
- -
- - - - - - - - -
- - - -
$ go run channel-directions.go
-passed message
-
- -
+

Go в примерах: Направления канала (Channel Directions)

- Next example: Select. + Следующий пример: Select.

diff --git a/public/channel-synchronization b/public/channel-synchronization index 7a0d3a3..b421afc 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -2,7 +2,7 @@ - Go by Example: Channel Synchronization + Go в примерах: Синхронизация канала (Channel Synchronization)
-

Go by Example: Channel Synchronization

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

We can use channels to synchronize execution -across goroutines. Here’s an example of using a -blocking receive to wait for a goroutine to finish. -When waiting for multiple goroutines to finish, -you may prefer to use a WaitGroup.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
-

This is the function we’ll run in a goroutine. The -done channel will be used to notify another -goroutine that this function’s work is done.

- -
- -
func worker(done chan bool) {
-    fmt.Print("working...")
-    time.Sleep(time.Second)
-    fmt.Println("done")
-
- -
-

Send a value to notify that we’re done.

- -
- -
    done <- true
-}
-
- -
- - - -
func main() {
-
- -
-

Start a worker goroutine, giving it the channel to -notify on.

- -
- -
    done := make(chan bool, 1)
-    go worker(done)
-
- -
-

Block until we receive a notification from the -worker on the channel.

- -
- -
    <-done
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run channel-synchronization.go      
-working...done                  
-
- -
-

If you removed the <- done line from this program, the -program would exit before the worker even -started.

- -
- - -
+

Go в примерах: Синхронизация канала (Channel Synchronization)

- Next example: Channel Directions. + Следующий пример: Направления канала (Channel Directions).

diff --git a/public/channels b/public/channels index 704c9f4..9711b17 100644 --- a/public/channels +++ b/public/channels @@ -2,7 +2,7 @@ - Go by Example: Channels + Go в примерах: Каналы (Channels)
-

Go by Example: Channels

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Channels are the pipes that connect concurrent -goroutines. You can send values into channels from one -goroutine and receive those values into another -goroutine.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

Create a new channel with make(chan val-type). -Channels are typed by the values they convey.

- -
- -
    messages := make(chan string)
-
- -
-

Send a value into a channel using the channel <- -syntax. Here we send "ping" to the messages -channel we made above, from a new goroutine.

- -
- -
    go func() { messages <- "ping" }()
-
- -
-

The <-channel syntax receives a value from the -channel. Here we’ll receive the "ping" message -we sent above and print it out.

- -
- -
    msg := <-messages
-    fmt.Println(msg)
-}
-
- -
- - - - - - - - - - - - - -
-

When we run the program the "ping" message is -successfully passed from one goroutine to another via -our channel.

- -
- -
$ go run channels.go 
-ping
-
- -
-

By default sends and receives block until both the -sender and receiver are ready. This property allowed -us to wait at the end of our program for the "ping" -message without having to use any other synchronization.

- -
- - -
+

Go в примерах: Каналы (Channels)

- Next example: Channel Buffering. + Следующий пример: Буферизированный канал (Channel Buffering).

diff --git a/public/closing-channels b/public/closing-channels index 8566518..fa1c91c 100644 --- a/public/closing-channels +++ b/public/closing-channels @@ -2,7 +2,7 @@ - Go by Example: Closing Channels + Go в примерах: Закрытие каналов (Closing Channels)
-

Go by Example: Closing Channels

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Closing a channel indicates that no more values -will be sent on it. This can be useful to communicate -completion to the channel’s receivers.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

In this example we’ll use a jobs channel to -communicate work to be done from the main() goroutine -to a worker goroutine. When we have no more jobs for -the worker we’ll close the jobs channel.

- -
- -
func main() {
-    jobs := make(chan int, 5)
-    done := make(chan bool)
-
- -
-

Here’s the worker goroutine. It repeatedly receives -from jobs with j, more := <-jobs. In this -special 2-value form of receive, the more value -will be false if jobs has been closed and all -values in the channel have already been received. -We use this to notify on done when we’ve worked -all our jobs.

- -
- -
    go func() {
-        for {
-            j, more := <-jobs
-            if more {
-                fmt.Println("received job", j)
-            } else {
-                fmt.Println("received all jobs")
-                done <- true
-                return
-            }
-        }
-    }()
-
- -
-

This sends 3 jobs to the worker over the jobs -channel, then closes it.

- -
- -
    for j := 1; j <= 3; j++ {
-        jobs <- j
-        fmt.Println("sent job", j)
-    }
-    close(jobs)
-    fmt.Println("sent all jobs")
-
- -
-

We await the worker using the -synchronization approach -we saw earlier.

- -
- -
    <-done
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run closing-channels.go 
-sent job 1
-received job 1
-sent job 2
-received job 2
-sent job 3
-received job 3
-sent all jobs
-received all jobs
-
- -
-

The idea of closed channels leads naturally to our next -example: range over channels.

- -
- - -
+

Go в примерах: Закрытие каналов (Closing Channels)

- Next example: Range over Channels. + Следующий пример: Перебор значений из каналов (Range over Channels).

diff --git a/public/closures b/public/closures index 36d6dc4..1d3cbc4 100644 --- a/public/closures +++ b/public/closures @@ -2,7 +2,7 @@ - Go by Example: Closures + Go в примерах: Замыкания (Closures)
-

Go by Example: Closures

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go supports anonymous functions, -which can form closures. -Anonymous functions are useful when you want to define -a function inline without having to name it.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

This function intSeq returns another function, which -we define anonymously in the body of intSeq. The -returned function closes over the variable i to -form a closure.

- -
- -
func intSeq() func() int {
-    i := 0
-    return func() int {
-        i++
-        return i
-    }
-}
-
- -
- - - -
func main() {
-
- -
-

We call intSeq, assigning the result (a function) -to nextInt. This function value captures its -own i value, which will be updated each time -we call nextInt.

- -
- -
    nextInt := intSeq()
-
- -
-

See the effect of the closure by calling nextInt -a few times.

- -
- -
    fmt.Println(nextInt())
-    fmt.Println(nextInt())
-    fmt.Println(nextInt())
-
- -
-

To confirm that the state is unique to that -particular function, create and test a new one.

- -
- -
    newInts := intSeq()
-    fmt.Println(newInts())
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run closures.go
-1
-2
-3
-1
-
- -
-

The last feature of functions we’ll look at for now is -recursion.

- -
- - -
+

Go в примерах: Замыкания (Closures)

- Next example: Recursion. + Следующий пример: Рекурсия (Recursion).

diff --git a/public/collection-functions b/public/collection-functions index 569c4b3..9efcde8 100644 --- a/public/collection-functions +++ b/public/collection-functions @@ -2,7 +2,7 @@ - Go by Example: Collection Functions + Go в примерах: Функции коллекции (Collection Functions)
-

Go by Example: Collection Functions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

We often need our programs to perform operations on -collections of data, like selecting all items that -satisfy a given predicate or mapping all items to a new -collection with a custom function.

- -
- - -
-

In some languages it’s idiomatic to use generic -data structures and algorithms. Go does not support -generics; in Go it’s common to provide collection -functions if and when they are specifically needed for -your program and data types.

- -
- - -
-

Here are some example collection functions for slices -of strings. You can use these examples to build your -own functions. Note that in some cases it may be -clearest to just inline the collection-manipulating -code directly, instead of creating and calling a -helper function.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "strings"
-)
-
- -
-

Index returns the first index of the target string t, or --1 if no match is found.

- -
- -
func Index(vs []string, t string) int {
-    for i, v := range vs {
-        if v == t {
-            return i
-        }
-    }
-    return -1
-}
-
- -
-

Include returns true if the target string t is in the -slice.

- -
- -
func Include(vs []string, t string) bool {
-    return Index(vs, t) >= 0
-}
-
- -
-

Any returns true if one of the strings in the slice -satisfies the predicate f.

- -
- -
func Any(vs []string, f func(string) bool) bool {
-    for _, v := range vs {
-        if f(v) {
-            return true
-        }
-    }
-    return false
-}
-
- -
-

All returns true if all of the strings in the slice -satisfy the predicate f.

- -
- -
func All(vs []string, f func(string) bool) bool {
-    for _, v := range vs {
-        if !f(v) {
-            return false
-        }
-    }
-    return true
-}
-
- -
-

Filter returns a new slice containing all strings in the -slice that satisfy the predicate f.

- -
- -
func Filter(vs []string, f func(string) bool) []string {
-    vsf := make([]string, 0)
-    for _, v := range vs {
-        if f(v) {
-            vsf = append(vsf, v)
-        }
-    }
-    return vsf
-}
-
- -
-

Map returns a new slice containing the results of applying -the function f to each string in the original slice.

- -
- -
func Map(vs []string, f func(string) string) []string {
-    vsm := make([]string, len(vs))
-    for i, v := range vs {
-        vsm[i] = f(v)
-    }
-    return vsm
-}
-
- -
- - - -
func main() {
-
- -
-

Here we try out our various collection functions.

- -
- -
    var strs = []string{"peach", "apple", "pear", "plum"}
-
- -
- - - -
    fmt.Println(Index(strs, "pear"))
-
- -
- - - -
    fmt.Println(Include(strs, "grape"))
-
- -
- - - -
    fmt.Println(Any(strs, func(v string) bool {
-        return strings.HasPrefix(v, "p")
-    }))
-
- -
- - - -
    fmt.Println(All(strs, func(v string) bool {
-        return strings.HasPrefix(v, "p")
-    }))
-
- -
- - - -
    fmt.Println(Filter(strs, func(v string) bool {
-        return strings.Contains(v, "e")
-    }))
-
- -
-

The above examples all used anonymous functions, -but you can also use named functions of the correct -type.

- -
- -
    fmt.Println(Map(strs, strings.ToUpper))
-
- -
- - - -
}
-
- -
- - - - - - - - -
- - - -
$ go run collection-functions.go 
-2
-false
-true
-false
-[peach apple pear]
-[PEACH APPLE PEAR PLUM]
-
- -
+

Go в примерах: Функции коллекции (Collection Functions)

- Next example: String Functions. + Следующий пример: Строковые функции (String Functions).

diff --git a/public/command-line-arguments b/public/command-line-arguments index 593e93f..d3857df 100644 --- a/public/command-line-arguments +++ b/public/command-line-arguments @@ -2,7 +2,7 @@ - Go by Example: Command-Line Arguments + Go в примерах: Аргументы командной строки (Command-Line Arguments)
-

Go by Example: Command-Line Arguments

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Command-line arguments -are a common way to parameterize execution of programs. -For example, go run hello.go uses run and -hello.go arguments to the go program.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "os"
-)
-
- -
- - - -
func main() {
-
- -
-

os.Args provides access to raw command-line -arguments. Note that the first value in this slice -is the path to the program, and os.Args[1:] -holds the arguments to the program.

- -
- -
    argsWithProg := os.Args
-    argsWithoutProg := os.Args[1:]
-
- -
-

You can get individual args with normal indexing.

- -
- -
    arg := os.Args[3]
-
- -
- - - -
    fmt.Println(argsWithProg)
-    fmt.Println(argsWithoutProg)
-    fmt.Println(arg)
-}
-
- -
- - - - - - - - - - - - - -
-

To experiment with command-line arguments it’s best to -build a binary with go build first.

- -
- -
$ go build command-line-arguments.go
-$ ./command-line-arguments a b c d
-[./command-line-arguments a b c d]       
-[a b c d]
-c
-
- -
-

Next we’ll look at more advanced command-line processing -with flags.

- -
- - -
+

Go в примерах: Аргументы командной строки (Command-Line Arguments)

- Next example: Command-Line Flags. + Следующий пример: Флаги командной строки (Command-Line Flags).

diff --git a/public/command-line-flags b/public/command-line-flags index 76e2bfc..97d6350 100644 --- a/public/command-line-flags +++ b/public/command-line-flags @@ -2,7 +2,7 @@ - Go by Example: Command-Line Flags + Go в примерах: Флаги командной строки (Command-Line Flags)
-

Go by Example: Command-Line Flags

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Command-line flags -are a common way to specify options for command-line -programs. For example, in wc -l the -l is a -command-line flag.

- -
- - -
- - - -
package main
-
- -
-

Go provides a flag package supporting basic -command-line flag parsing. We’ll use this package to -implement our example command-line program.

- -
- -
import (
-    "flag"
-    "fmt"
-)
-
- -
- - - -
func main() {
-
- -
-

Basic flag declarations are available for string, -integer, and boolean options. Here we declare a -string flag word with a default value "foo" -and a short description. This flag.String function -returns a string pointer (not a string value); -we’ll see how to use this pointer below.

- -
- -
    wordPtr := flag.String("word", "foo", "a string")
-
- -
-

This declares numb and fork flags, using a -similar approach to the word flag.

- -
- -
    numbPtr := flag.Int("numb", 42, "an int")
-    boolPtr := flag.Bool("fork", false, "a bool")
-
- -
-

It’s also possible to declare an option that uses an -existing var declared elsewhere in the program. -Note that we need to pass in a pointer to the flag -declaration function.

- -
- -
    var svar string
-    flag.StringVar(&svar, "svar", "bar", "a string var")
-
- -
-

Once all flags are declared, call flag.Parse() -to execute the command-line parsing.

- -
- -
    flag.Parse()
-
- -
-

Here we’ll just dump out the parsed options and -any trailing positional arguments. Note that we -need to dereference the pointers with e.g. *wordPtr -to get the actual option values.

- -
- -
    fmt.Println("word:", *wordPtr)
-    fmt.Println("numb:", *numbPtr)
-    fmt.Println("fork:", *boolPtr)
-    fmt.Println("svar:", svar)
-    fmt.Println("tail:", flag.Args())
-}
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

To experiment with the command-line flags program it’s -best to first compile it and then run the resulting -binary directly.

- -
- -
$ go build command-line-flags.go
-
- -
-

Try out the built program by first giving it values for -all flags.

- -
- -
$ ./command-line-flags -word=opt -numb=7 -fork -svar=flag
-word: opt
-numb: 7
-fork: true
-svar: flag
-tail: []
-
- -
-

Note that if you omit flags they automatically take -their default values.

- -
- -
$ ./command-line-flags -word=opt
-word: opt
-numb: 42
-fork: false
-svar: bar
-tail: []
-
- -
-

Trailing positional arguments can be provided after -any flags.

- -
- -
$ ./command-line-flags -word=opt a1 a2 a3
-word: opt
-...
-tail: [a1 a2 a3]
-
- -
-

Note that the flag package requires all flags to -appear before positional arguments (otherwise the flags -will be interpreted as positional arguments).

- -
- -
$ ./command-line-flags -word=opt a1 a2 a3 -numb=7
-word: opt
-numb: 42
-fork: false
-svar: bar
-tail: [a1 a2 a3 -numb=7]
-
- -
-

Use -h or --help flags to get automatically -generated help text for the command-line program.

- -
- -
$ ./command-line-flags -h
-Usage of ./command-line-flags:
-  -fork=false: a bool
-  -numb=42: an int
-  -svar="bar": a string var
-  -word="foo": a string
-
- -
-

If you provide a flag that wasn’t specified to the -flag package, the program will print an error message -and show the help text again.

- -
- -
$ ./command-line-flags -wat
-flag provided but not defined: -wat
-Usage of ./command-line-flags:
-...
-
- -
+

Go в примерах: Флаги командной строки (Command-Line Flags)

- Next example: Command-Line Subcommands. + Следующий пример: Подкоманды командной строки (Command-Line Subcommands).

diff --git a/public/command-line-subcommands b/public/command-line-subcommands index f5add93..f90fce7 100644 --- a/public/command-line-subcommands +++ b/public/command-line-subcommands @@ -2,7 +2,7 @@ - Go by Example: Command-Line Subcommands + Go в примерах: Подкоманды командной строки (Command-Line Subcommands)
-

Go by Example: Command-Line Subcommands

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Some command-line tools, like the go tool or git -have many subcommands, each with its own set of -flags. For example, go build and go get are two -different subcommands of the go tool. -The flag package lets us easily define simple -subcommands that have their own flags.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "flag"
-    "fmt"
-    "os"
-)
-
- -
- - - -
func main() {
-
- -
-

We declare a subcommand using the NewFlagSet -function, and proceed to define new flags specific -for this subcommand.

- -
- -
    fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
-    fooEnable := fooCmd.Bool("enable", false, "enable")
-    fooName := fooCmd.String("name", "", "name")
-
- -
-

For a different subcommand we can define different -supported flags.

- -
- -
    barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
-    barLevel := barCmd.Int("level", 0, "level")
-
- -
-

The subcommand is expected as the first argument -to the program.

- -
- -
    if len(os.Args) < 2 {
-        fmt.Println("expected 'foo' or 'bar' subcommands")
-        os.Exit(1)
-    }
-
- -
-

Check which subcommand is invoked.

- -
- -
    switch os.Args[1] {
-
- -
-

For every subcommand, we parse its own flags and -have access to trailing positional arguments.

- -
- -
    case "foo":
-        fooCmd.Parse(os.Args[2:])
-        fmt.Println("subcommand 'foo'")
-        fmt.Println("  enable:", *fooEnable)
-        fmt.Println("  name:", *fooName)
-        fmt.Println("  tail:", fooCmd.Args())
-    case "bar":
-        barCmd.Parse(os.Args[2:])
-        fmt.Println("subcommand 'bar'")
-        fmt.Println("  level:", *barLevel)
-        fmt.Println("  tail:", barCmd.Args())
-    default:
-        fmt.Println("expected 'foo' or 'bar' subcommands")
-        os.Exit(1)
-    }
-}
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
$ go build command-line-subcommands.go 
-
- -
-

First invoke the foo subcommand.

- -
- -
$ ./command-line-subcommands foo -enable -name=joe a1 a2
-subcommand 'foo'
-  enable: true
-  name: joe
-  tail: [a1 a2]
-
- -
-

Now try bar.

- -
- -
$ ./command-line-subcommands bar -level 8 a1
-subcommand 'bar'
-  level: 8
-  tail: [a1]
-
- -
-

But bar won’t accept foo’s flags.

- -
- -
$ ./command-line-subcommands bar -enable a1
-flag provided but not defined: -enable
-Usage of bar:
-  -level int
-        level
-
- -
-

Next we’ll look at environment variables, another common -way to parameterize programs.

- -
- - -
+

Go в примерах: Подкоманды командной строки (Command-Line Subcommands)

- Next example: Environment Variables. + Следующий пример: Переменные среды (Environment Variables).

diff --git a/public/constants b/public/constants index 31e2c7b..bc51abe 100644 --- a/public/constants +++ b/public/constants @@ -2,7 +2,7 @@ - Go by Example: Constants + Go в примерах: Константы (Constants)
-

Go by Example: Constants

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go supports constants of character, string, boolean, -and numeric values.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "math"
-)
-
- -
-

const declares a constant value.

- -
- -
const s string = "constant"
-
- -
- - - -
func main() {
-    fmt.Println(s)
-
- -
-

A const statement can appear anywhere a var -statement can.

- -
- -
    const n = 500000000
-
- -
-

Constant expressions perform arithmetic with -arbitrary precision.

- -
- -
    const d = 3e20 / n
-    fmt.Println(d)
-
- -
-

A numeric constant has no type until it’s given -one, such as by an explicit conversion.

- -
- -
    fmt.Println(int64(d))
-
- -
-

A number can be given a type by using it in a -context that requires one, such as a variable -assignment or function call. For example, here -math.Sin expects a float64.

- -
- -
    fmt.Println(math.Sin(n))
-}
-
- -
- - - - - - - - -
- - - -
$ go run constant.go 
-constant
-6e+11
-600000000000
--0.28470407323754404
-
- -
+

Go в примерах: Константы (Constants)

- Next example: For. + Следующий пример: Цикл For.

diff --git a/public/defer b/public/defer index f99d59d..2beb109 100644 --- a/public/defer +++ b/public/defer @@ -2,7 +2,7 @@ - Go by Example: Defer + Go в примерах: Defer
-

Go by Example: Defer

+

Go в примерах: Defer

-

Defer is used to ensure that a function call is -performed later in a program’s execution, usually for -purposes of cleanup. defer is often used where e.g. -ensure and finally would be used in other languages.

+

Defer используется, чтобы гарантировать, что +вызов функции будет выполнен позже при выполнении +программы, обычно для целей очистки. defer часто +используется там, где в других языках используются +ensure и finally.

@@ -44,7 +45,7 @@ purposes of cleanup. defer is often used where e.g. - +
package main
 
@@ -68,9 +69,9 @@ purposes of cleanup. defer is often used where e.g.
-

Suppose we wanted to create a file, write to it, -and then close when we’re done. Here’s how we could -do that with defer.

+

Предположим, мы хотим создать файл, записать в него, +а затем закрыть, когда закончим. Вот как нам поможет +defer.

@@ -83,11 +84,11 @@ do that with defer.

-

Immediately after getting a file object with -createFile, we defer the closing of that file -with closeFile. This will be executed at the end -of the enclosing function (main), after -writeFile has finished.

+

Сразу же после получения объекта файла с помощью +createFile мы откладываем закрытие этого файла +с помощью closeFile. Она будет выполнена в +конце включающей функции (main) после завершения +writeFile.

@@ -148,8 +149,8 @@ of the enclosing function (main), after
-

It’s important to check for errors when closing a -file, even in a deferred function.

+

Важно проверять наличие ошибок при закрытии файла, +даже в отложенной функции.

@@ -184,8 +185,8 @@ file, even in a deferred function.

-

Running the program confirms that the file is closed -after being written.

+

Запуск программы подтверждает, что файл закрыт +после записи.

@@ -203,7 +204,7 @@ after being written.

- Next example: Collection Functions. + Следующий пример: Функции коллекции (Collection Functions).

-

Go by Example: Directories

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go has several useful functions for working with -directories in the file system.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "io/ioutil"
-    "os"
-    "path/filepath"
-)
-
- -
- - - -
func check(e error) {
-    if e != nil {
-        panic(e)
-    }
-}
-
- -
- - - -
func main() {
-
- -
-

Create a new sub-directory in the current working -directory.

- -
- -
    err := os.Mkdir("subdir", 0755)
-    check(err)
-
- -
-

When creating temporary directories, it’s good -practice to defer their removal. os.RemoveAll -will delete a whole directory tree (similarly to -rm -rf).

- -
- -
    defer os.RemoveAll("subdir")
-
- -
-

Helper function to create a new empty file.

- -
- -
    createEmptyFile := func(name string) {
-        d := []byte("")
-        check(ioutil.WriteFile(name, d, 0644))
-    }
-
- -
- - - -
    createEmptyFile("subdir/file1")
-
- -
-

We can create a hierarchy of directories, including -parents with MkdirAll. This is similar to the -command-line mkdir -p.

- -
- -
    err = os.MkdirAll("subdir/parent/child", 0755)
-    check(err)
-
- -
- - - -
    createEmptyFile("subdir/parent/file2")
-    createEmptyFile("subdir/parent/file3")
-    createEmptyFile("subdir/parent/child/file4")
-
- -
-

ReadDir lists directory contents, returning a -slice of os.FileInfo objects.

- -
- -
    c, err := ioutil.ReadDir("subdir/parent")
-    check(err)
-
- -
- - - -
    fmt.Println("Listing subdir/parent")
-    for _, entry := range c {
-        fmt.Println(" ", entry.Name(), entry.IsDir())
-    }
-
- -
-

Chdir lets us change the current working directory, -similarly to cd.

- -
- -
    err = os.Chdir("subdir/parent/child")
-    check(err)
-
- -
-

Now we’ll see the contents of subdir/parent/child -when listing the current directory.

- -
- -
    c, err = ioutil.ReadDir(".")
-    check(err)
-
- -
- - - -
    fmt.Println("Listing subdir/parent/child")
-    for _, entry := range c {
-        fmt.Println(" ", entry.Name(), entry.IsDir())
-    }
-
- -
-

cd back to where we started.

- -
- -
    err = os.Chdir("../../..")
-    check(err)
-
- -
-

We can also visit a directory recursively, -including all its sub-directories. Walk accepts -a callback function to handle every file or -directory visited.

- -
- -
    fmt.Println("Visiting subdir")
-    err = filepath.Walk("subdir", visit)
-}
-
- -
-

visit is called for every file or directory found -recursively by filepath.Walk.

- -
- -
func visit(p string, info os.FileInfo, err error) error {
-    if err != nil {
-        return err
-    }
-    fmt.Println(" ", p, info.IsDir())
-    return nil
-}
-
- -
- - - - - - - - -
- - - -
$ go run directories.go
-Listing subdir/parent
-  child true
-  file2 false
-  file3 false
-Listing subdir/parent/child
-  file4 false
-Visiting subdir
-  subdir true
-  subdir/file1 false
-  subdir/parent true
-  subdir/parent/child true
-  subdir/parent/child/file4 false
-  subdir/parent/file2 false
-  subdir/parent/file3 false
-
- -
+

Go в примерах: Директории (Directories)

- Next example: Temporary Files and Directories. + Следующий пример: Временные файлы и директории (Temporary Files and Directories).

diff --git a/public/environment-variables b/public/environment-variables index 25504ae..c08bf0e 100644 --- a/public/environment-variables +++ b/public/environment-variables @@ -2,7 +2,7 @@ - Go by Example: Environment Variables + Go в примерах: Переменные среды (Environment Variables)
-

Go by Example: Environment Variables

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Environment variables -are a universal mechanism for conveying configuration -information to Unix programs. -Let’s look at how to set, get, and list environment variables.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "os"
-    "strings"
-)
-
- -
- - - -
func main() {
-
- -
-

To set a key/value pair, use os.Setenv. To get a -value for a key, use os.Getenv. This will return -an empty string if the key isn’t present in the -environment.

- -
- -
    os.Setenv("FOO", "1")
-    fmt.Println("FOO:", os.Getenv("FOO"))
-    fmt.Println("BAR:", os.Getenv("BAR"))
-
- -
-

Use os.Environ to list all key/value pairs in the -environment. This returns a slice of strings in the -form KEY=value. You can strings.Split them to -get the key and value. Here we print all the keys.

- -
- -
    fmt.Println()
-    for _, e := range os.Environ() {
-        pair := strings.Split(e, "=")
-        fmt.Println(pair[0])
-    }
-}
-
- -
- - - - - - - - - - - - - - - - - - -
-

Running the program shows that we pick up the value -for FOO that we set in the program, but that -BAR is empty.

- -
- -
$ go run environment-variables.go
-FOO: 1
-BAR: 
-
- -
-

The list of keys in the environment will depend on your -particular machine.

- -
- -
TERM_PROGRAM
-PATH
-SHELL
-...
-
- -
-

If we set BAR in the environment first, the running -program picks that value up.

- -
- -
$ BAR=2 go run environment-variables.go
-FOO: 1
-BAR: 2
-...
-
- -
+

Go в примерах: Переменные среды (Environment Variables)

- Next example: HTTP Clients. + Следующий пример: HTTP клиенты (HTTP Clients).

diff --git a/public/epoch b/public/epoch index 76a9b20..ddd321a 100644 --- a/public/epoch +++ b/public/epoch @@ -2,7 +2,7 @@ - Go by Example: Epoch + Go в примерах: Epoch
-

Go by Example: Epoch

+

Go в примерах: Epoch

-

A common requirement in programs is getting the number -of seconds, milliseconds, or nanoseconds since the -Unix epoch. -Here’s how to do it in Go.

+

Общим требованием в программах является получение +количества секунд, миллисекунд или наносекунд в Unixtime. +Вот как это сделать в Go.

@@ -44,7 +43,7 @@ Here’s how to do it in Go.

- +
package main
 
@@ -80,9 +79,9 @@ Here’s how to do it in Go.

-

Use time.Now with Unix or UnixNano to get -elapsed time since the Unix epoch in seconds or -nanoseconds, respectively.

+

Используйте time.Now с Unix или UnixNano, +чтобы получить время, прошедшее с начала эпохи Unix в +секундах или наносекундах соответственно.

@@ -98,9 +97,9 @@ nanoseconds, respectively.

-

Note that there is no UnixMillis, so to get the -milliseconds since epoch you’ll need to manually -divide from nanoseconds.

+

Обратите внимание, что UnixMillis не существует, +поэтому, чтобы получить миллисекунды с начала эпохи Unix, +вам нужно будет вручную делить наносекунды.

@@ -116,8 +115,8 @@ divide from nanoseconds.

-

You can also convert integer seconds or nanoseconds -since the epoch into the corresponding time.

+

Вы также можете конвертировать целые секунды или наносекунды +Unixtime в соответствующее время.

@@ -154,8 +153,8 @@ since the epoch into the corresponding time.

-

Next we’ll look at another time-related task: time -parsing and formatting.

+

Далее мы рассмотрим еще одну задачу, связанную со +временем: разбор и форматирование времени.

@@ -168,7 +167,7 @@ parsing and formatting.

- Next example: Time Formatting / Parsing. + Следующий пример: Форматирование времени (Time Formatting / Parsing).

-

Go by Example: Errors

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

In Go it’s idiomatic to communicate errors via an -explicit, separate return value. This contrasts with -the exceptions used in languages like Java and Ruby and -the overloaded single result / error value sometimes -used in C. Go’s approach makes it easy to see which -functions return errors and to handle them using the -same language constructs employed for any other, -non-error tasks.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "errors"
-    "fmt"
-)
-
- -
-

By convention, errors are the last return value and -have type error, a built-in interface.

- -
- -
func f1(arg int) (int, error) {
-    if arg == 42 {
-
- -
-

errors.New constructs a basic error value -with the given error message.

- -
- -
        return -1, errors.New("can't work with 42")
-
- -
- - - -
    }
-
- -
-

A nil value in the error position indicates that -there was no error.

- -
- -
    return arg + 3, nil
-}
-
- -
-

It’s possible to use custom types as errors by -implementing the Error() method on them. Here’s a -variant on the example above that uses a custom type -to explicitly represent an argument error.

- -
- -
type argError struct {
-    arg  int
-    prob string
-}
-
- -
- - - -
func (e *argError) Error() string {
-    return fmt.Sprintf("%d - %s", e.arg, e.prob)
-}
-
- -
- - - -
func f2(arg int) (int, error) {
-    if arg == 42 {
-
- -
-

In this case we use &argError syntax to build -a new struct, supplying values for the two -fields arg and prob.

- -
- -
        return -1, &argError{arg, "can't work with it"}
-    }
-    return arg + 3, nil
-}
-
- -
- - - -
func main() {
-
- -
-

The two loops below test out each of our -error-returning functions. Note that the use of an -inline error check on the if line is a common -idiom in Go code.

- -
- -
    for _, i := range []int{7, 42} {
-        if r, e := f1(i); e != nil {
-            fmt.Println("f1 failed:", e)
-        } else {
-            fmt.Println("f1 worked:", r)
-        }
-    }
-    for _, i := range []int{7, 42} {
-        if r, e := f2(i); e != nil {
-            fmt.Println("f2 failed:", e)
-        } else {
-            fmt.Println("f2 worked:", r)
-        }
-    }
-
- -
-

If you want to programmatically use the data in -a custom error, you’ll need to get the error as an -instance of the custom error type via type -assertion.

- -
- -
    _, e := f2(42)
-    if ae, ok := e.(*argError); ok {
-        fmt.Println(ae.arg)
-        fmt.Println(ae.prob)
-    }
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run errors.go
-f1 worked: 10
-f1 failed: can't work with 42
-f2 worked: 10
-f2 failed: 42 - can't work with it
-42
-can't work with it
-
- -
-

See this great post -on the Go blog for more on error handling.

- -
- - -
+

Go в примерах: Ошибки (Errors)

- Next example: Goroutines. + Следующий пример: Горутины (Goroutines).

diff --git a/public/execing-processes b/public/execing-processes index 98ce62a..e0cc10d 100644 --- a/public/execing-processes +++ b/public/execing-processes @@ -2,7 +2,7 @@ - Go by Example: Exec'ing Processes + Go в примерах: Исполняющие процессы (Exec'ing Processes)
-

Go by Example: Exec'ing Processes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

In the previous example we looked at -spawning external processes. We -do this when we need an external process accessible to -a running Go process. Sometimes we just want to -completely replace the current Go process with another -(perhaps non-Go) one. To do this we’ll use Go’s -implementation of the classic -exec -function.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "os"
-    "os/exec"
-    "syscall"
-)
-
- -
- - - -
func main() {
-
- -
-

For our example we’ll exec ls. Go requires an -absolute path to the binary we want to execute, so -we’ll use exec.LookPath to find it (probably -/bin/ls).

- -
- -
    binary, lookErr := exec.LookPath("ls")
-    if lookErr != nil {
-        panic(lookErr)
-    }
-
- -
-

Exec requires arguments in slice form (as -apposed to one big string). We’ll give ls a few -common arguments. Note that the first argument should -be the program name.

- -
- -
    args := []string{"ls", "-a", "-l", "-h"}
-
- -
-

Exec also needs a set of environment variables -to use. Here we just provide our current -environment.

- -
- -
    env := os.Environ()
-
- -
-

Here’s the actual syscall.Exec call. If this call is -successful, the execution of our process will end -here and be replaced by the /bin/ls -a -l -h -process. If there is an error we’ll get a return -value.

- -
- -
    execErr := syscall.Exec(binary, args, env)
-    if execErr != nil {
-        panic(execErr)
-    }
-}
-
- -
- - - - - - - - - - - - - -
-

When we run our program it is replaced by ls.

- -
- -
$ go run execing-processes.go
-total 16
-drwxr-xr-x  4 mark 136B Oct 3 16:29 .
-drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
--rw-r--r--  1 mark 1.3K Oct 3 16:28 execing-processes.go
-
- -
-

Note that Go does not offer a classic Unix fork -function. Usually this isn’t an issue though, since -starting goroutines, spawning processes, and exec’ing -processes covers most use cases for fork.

- -
- - -
+

Go в примерах: Исполняющие процессы (Exec'ing Processes)

- Next example: Signals. + Следующий пример: Сигналы (Signals).

diff --git a/public/exit b/public/exit index 5929eb6..50c7fbe 100644 --- a/public/exit +++ b/public/exit @@ -2,7 +2,7 @@ - Go by Example: Exit + Go в примерах: Выход (Exit)
-

Go by Example: Exit

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Use os.Exit to immediately exit with a given -status.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "os"
-)
-
- -
- - - -
func main() {
-
- -
-

defers will not be run when using os.Exit, so -this fmt.Println will never be called.

- -
- -
    defer fmt.Println("!")
-
- -
-

Exit with status 3.

- -
- -
    os.Exit(3)
-}
-
- -
-

Note that unlike e.g. C, Go does not use an integer -return value from main to indicate exit status. If -you’d like to exit with a non-zero status you should -use os.Exit.

- -
- - -
- - - - - - - - - - - - - - - - - - -
-

If you run exit.go using go run, the exit -will be picked up by go and printed.

- -
- -
$ go run exit.go
-exit status 3
-
- -
-

By building and executing a binary you can see -the status in the terminal.

- -
- -
$ go build exit.go
-$ ./exit
-$ echo $?
-3
-
- -
-

Note that the ! from our program never got printed.

- -
- - -
+

Go в примерах: Выход (Exit)

diff --git a/public/file-paths b/public/file-paths index 2351954..b026eb7 100644 --- a/public/file-paths +++ b/public/file-paths @@ -2,7 +2,7 @@ - Go by Example: File Paths + Go в примерах: Пути к файлам (File Paths)
-

Go by Example: File Paths

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

The filepath package provides functions to parse -and construct file paths in a way that is portable -between operating systems; dir/file on Linux vs. -dir\file on Windows, for example.

- -
- -
package main
-
- -
- - - -
import (
-    "fmt"
-    "path/filepath"
-    "strings"
-)
-
- -
- - - -
func main() {
-
- -
-

Join should be used to construct paths in a -portable way. It takes any number of arguments -and constructs a hierarchical path from them.

- -
- -
    p := filepath.Join("dir1", "dir2", "filename")
-    fmt.Println("p:", p)
-
- -
-

You should always use Join instead of -concatenating /s or \s manually. In addition -to providing portability, Join will also -normalize paths by removing superfluous separators -and directory changes.

- -
- -
    fmt.Println(filepath.Join("dir1//", "filename"))
-    fmt.Println(filepath.Join("dir1/../dir1", "filename"))
-
- -
-

Dir and Base can be used to split a path to the -directory and the file. Alternatively, Split will -return both in the same call.

- -
- -
    fmt.Println("Dir(p):", filepath.Dir(p))
-    fmt.Println("Base(p):", filepath.Base(p))
-
- -
-

We can check whether a path is absolute.

- -
- -
    fmt.Println(filepath.IsAbs("dir/file"))
-    fmt.Println(filepath.IsAbs("/dir/file"))
-
- -
- - - -
    filename := "config.json"
-
- -
-

Some file names have extensions following a dot. We -can split the extension out of such names with Ext.

- -
- -
    ext := filepath.Ext(filename)
-    fmt.Println(ext)
-
- -
-

To find the file’s name with the extension removed, -use strings.TrimSuffix.

- -
- -
    fmt.Println(strings.TrimSuffix(filename, ext))
-
- -
-

Rel finds a relative path between a base and a -target. It returns an error if the target cannot -be made relative to base.

- -
- -
    rel, err := filepath.Rel("a/b", "a/b/t/file")
-    if err != nil {
-        panic(err)
-    }
-    fmt.Println(rel)
-
- -
- - - -
    rel, err = filepath.Rel("a/b", "a/c/t/file")
-    if err != nil {
-        panic(err)
-    }
-    fmt.Println(rel)
-}
-
- -
- - - - - - - - -
- - - -
$ go run file-paths.go
-p: dir1/dir2/filename
-dir1/filename
-dir1/filename
-Dir(p): dir1/dir2
-Base(p): filename
-false
-true
-.json
-config
-t/file
-../c/t/file
-
- -
+

Go в примерах: Пути к файлам (File Paths)

- Next example: Directories. + Следующий пример: Директории (Directories).

diff --git a/public/for b/public/for index 81b98d9..de2ea5f 100644 --- a/public/for +++ b/public/for @@ -2,7 +2,7 @@ - Go by Example: For + Go в примерах: Цикл For
-

Go by Example: For

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

for is Go’s only looping construct. Here are -three basic types of for loops.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

The most basic type, with a single condition.

- -
- -
    i := 1
-    for i <= 3 {
-        fmt.Println(i)
-        i = i + 1
-    }
-
- -
-

A classic initial/condition/after for loop.

- -
- -
    for j := 7; j <= 9; j++ {
-        fmt.Println(j)
-    }
-
- -
-

for without a condition will loop repeatedly -until you break out of the loop or return from -the enclosing function.

- -
- -
    for {
-        fmt.Println("loop")
-        break
-    }
-
- -
-

You can also continue to the next iteration of -the loop.

- -
- -
    for n := 0; n <= 5; n++ {
-        if n%2 == 0 {
-            continue
-        }
-        fmt.Println(n)
-    }
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run for.go
-1
-2
-3
-7
-8
-9
-loop
-1
-3
-5
-
- -
-

We’ll see some other for forms later when we look at -range statements, channels, and other data -structures.

- -
- - -
+

Go в примерах: Цикл For

- Next example: If/Else. + Следующий пример: If/Else.

diff --git a/public/functions b/public/functions index 8880847..ef4f0db 100644 --- a/public/functions +++ b/public/functions @@ -2,7 +2,7 @@ - Go by Example: Functions + Go в примерах: Функции (Functions)
-

Go by Example: Functions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Functions are central in Go. We’ll learn about -functions with a few different examples.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

Here’s a function that takes two ints and returns -their sum as an int.

- -
- -
func plus(a int, b int) int {
-
- -
-

Go requires explicit returns, i.e. it won’t -automatically return the value of the last -expression.

- -
- -
    return a + b
-}
-
- -
-

When you have multiple consecutive parameters of -the same type, you may omit the type name for the -like-typed parameters up to the final parameter that -declares the type.

- -
- -
func plusPlus(a, b, c int) int {
-    return a + b + c
-}
-
- -
- - - -
func main() {
-
- -
-

Call a function just as you’d expect, with -name(args).

- -
- -
    res := plus(1, 2)
-    fmt.Println("1+2 =", res)
-
- -
- - - -
    res = plusPlus(1, 2, 3)
-    fmt.Println("1+2+3 =", res)
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run functions.go 
-1+2 = 3
-1+2+3 = 6
-
- -
-

There are several other features to Go functions. One is -multiple return values, which we’ll look at next.

- -
- - -
+

Go в примерах: Функции (Functions)

- Next example: Multiple Return Values. + Следующий пример: Функции с множественным возвратом (Multiple Return Values).

diff --git a/public/goroutines b/public/goroutines index 6b87012..dfcbc2d 100644 --- a/public/goroutines +++ b/public/goroutines @@ -2,7 +2,7 @@ - Go by Example: Goroutines + Go в примерах: Горутины (Goroutines)
-

Go by Example: Goroutines

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

A goroutine is a lightweight thread of execution.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
- - - -
func f(from string) {
-    for i := 0; i < 3; i++ {
-        fmt.Println(from, ":", i)
-    }
-}
-
- -
- - - -
func main() {
-
- -
-

Suppose we have a function call f(s). Here’s how -we’d call that in the usual way, running it -synchronously.

- -
- -
    f("direct")
-
- -
-

To invoke this function in a goroutine, use -go f(s). This new goroutine will execute -concurrently with the calling one.

- -
- -
    go f("goroutine")
-
- -
-

You can also start a goroutine for an anonymous -function call.

- -
- -
    go func(msg string) {
-        fmt.Println(msg)
-    }("going")
-
- -
-

Our two function calls are running asynchronously in -separate goroutines now. Wait for them to finish -(for a more robust approach, use a WaitGroup).

- -
- -
    time.Sleep(time.Second)
-    fmt.Println("done")
-}
-
- -
- - - - - - - - - - - - - -
-

When we run this program, we see the output of the -blocking call first, then the interleaved output of the -two goroutines. This interleaving reflects the -goroutines being run concurrently by the Go runtime.

- -
- -
$ go run goroutines.go
-direct : 0
-direct : 1
-direct : 2
-goroutine : 0
-going
-goroutine : 1
-goroutine : 2
-done
-
- -
-

Next we’ll look at a complement to goroutines in -concurrent Go programs: channels.

- -
- - -
+

Go в примерах: Горутины (Goroutines)

- Next example: Channels. + Следующий пример: Каналы (Channels).

diff --git a/public/hello-world b/public/hello-world index 4c2373a..67c1c82 100644 --- a/public/hello-world +++ b/public/hello-world @@ -2,7 +2,7 @@ - Go by Example: Hello World + Go в примерах: Hello World
-

Go by Example: Hello World

+

Go в примерах: Hello World

-

Our first program will print the classic “hello world” -message. Here’s the full source code.

+

Наша первая программа напечатает классическое сообщение “hello world” +Полный код.

- +
package main
 
@@ -126,7 +126,7 @@ learn more about the language.

- Next example: Values. + Следующий пример: Типы данных (Values).

+

Go в примерах: HTTP серверы (HTTP Servers)

+ + +

+ Следующий пример: Порождающие процессы (Spawning Processes). +

+ + +
+ + + + diff --git a/public/http-clients b/public/http-clients deleted file mode 100644 index 7bdaa06..0000000 --- a/public/http-clients +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Go by Example: HTTP Clients - - - - -
-

Go by Example: HTTP Clients

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

The Go standard library comes with excellent support -for HTTP clients and servers in the net/http -package. In this example we’ll use it to issue simple -HTTP requests.

- -
- -
package main
-
- -
- - - -
import (
-    "bufio"
-    "fmt"
-    "net/http"
-)
-
- -
- - - -
func main() {
-
- -
-

Issue an HTTP GET request to a server. http.Get is a -convenient shortcut around creating an http.Client -object and calling its Get method; it uses the -http.DefaultClient object which has useful default -settings.

- -
- -
    resp, err := http.Get("http://gobyexample.com")
-    if err != nil {
-        panic(err)
-    }
-    defer resp.Body.Close()
-
- -
-

Print the HTTP response status.

- -
- -
    fmt.Println("Response status:", resp.Status)
-
- -
-

Print the first 5 lines of the response body.

- -
- -
    scanner := bufio.NewScanner(resp.Body)
-    for i := 0; scanner.Scan() && i < 5; i++ {
-        fmt.Println(scanner.Text())
-    }
-
- -
- - - -
    if err := scanner.Err(); err != nil {
-        panic(err)
-    }
-}
-
- -
- - - - - - - - -
- - - -
$ go run http-clients.go
-Response status: 200 OK
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>Go by Example</title>
-
- -
- - -

- Next example: HTTP Servers. -

- - -
- - - - diff --git a/public/http-servers b/public/http-servers deleted file mode 100644 index aa2802d..0000000 --- a/public/http-servers +++ /dev/null @@ -1,217 +0,0 @@ - - - - - Go by Example: HTTP Servers - - - - -
-

Go by Example: HTTP Servers

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Writing a basic HTTP server is easy using the -net/http package.

- -
- -
package main
-
- -
- - - -
import (
-    "fmt"
-    "net/http"
-)
-
- -
-

A fundamental concept in net/http servers is -handlers. A handler is an object implementing the -http.Handler interface. A common way to write -a handler is by using the http.HandlerFunc adapter -on functions with the appropriate signature.

- -
- -
func hello(w http.ResponseWriter, req *http.Request) {
-
- -
-

Functions serving as handlers take a -http.ResponseWriter and a http.Request as -arguments. The response writer is used to fill in the -HTTP response. Here our simple response is just -“hello\n”.

- -
- -
    fmt.Fprintf(w, "hello\n")
-}
-
- -
- - - -
func headers(w http.ResponseWriter, req *http.Request) {
-
- -
-

This handler does something a little more -sophisticated by reading all the HTTP request -headers and echoing them into the response body.

- -
- -
    for name, headers := range req.Header {
-        for _, h := range headers {
-            fmt.Fprintf(w, "%v: %v\n", name, h)
-        }
-    }
-}
-
- -
- - - -
func main() {
-
- -
-

We register our handlers on server routes using the -http.HandleFunc convenience function. It sets up -the default router in the net/http package and -takes a function as an argument.

- -
- -
    http.HandleFunc("/hello", hello)
-    http.HandleFunc("/headers", headers)
-
- -
-

Finally, we call the ListenAndServe with the port -and a handler. nil tells it to use the default -router we’ve just set up.

- -
- -
    http.ListenAndServe(":8090", nil)
-}
-
- -
- - - - - - - - - - - - - -
-

Run the server in the background.

- -
- -
$ go run http-servers.go &
-
- -
-

Access the /hello route.

- -
- -
$ curl localhost:8090/hello
-hello
-
- -
- - -

- Next example: Spawning Processes. -

- - -
- - - - diff --git a/public/if-else b/public/if-else index f00d6b5..fc7514b 100644 --- a/public/if-else +++ b/public/if-else @@ -2,7 +2,7 @@ - Go by Example: If/Else + Go в примерах: If/Else
-

Go by Example: If/Else

+

Go в примерах: If/Else

-

Branching with if and else in Go is -straight-forward.

+

Условные операторы if иelse в Go +выглядят достаточно стандартно

@@ -42,7 +42,7 @@ straight-forward.

- +
package main
 
@@ -75,7 +75,7 @@ straight-forward.

-

Here’s a basic example.

+

Стандартное использование

@@ -92,7 +92,7 @@ straight-forward.

-

You can have an if statement without an else.

+

Вы можете использовать блоке if без блока else.

@@ -107,9 +107,9 @@ straight-forward.

-

A statement can precede conditionals; any variables -declared in this statement are available in all -branches.

+

Присваивание переменной может происходить до условия. +Любые определенные значения будут доступны в +последующих ветках

@@ -129,8 +129,8 @@ branches.

-

Note that you don’t need parentheses around conditions -in Go, but that the braces are required.

+

Имейте ввиду, что в Go не надо использовать скобки в условии, +но блок необходимо заключать в фигурные скобки

@@ -175,7 +175,7 @@ for basic conditions.

- Next example: Switch. + Следующий пример: Switch.

-

Go by Example

+

Go в примерах

- Go is an - open source programming language designed for - building simple, fast, and reliable software. + Go - это язык программирования с + открытым исходным кодом, предназначенный для создания простого, + быстрого и надежного программного обеспечения.

- Go by Example is a hands-on introduction - to Go using annotated example programs. Check out - the first example or - browse the full list below. + Go в примерах Go by Example - это практическое введение + в Go с использованием примеров реальных программ. Проверьте + первый пример или просмотрите полный + список ниже.

diff --git a/public/interfaces b/public/interfaces index fad0ed0..9c13931 100644 --- a/public/interfaces +++ b/public/interfaces @@ -2,7 +2,7 @@ - Go by Example: Interfaces + Go в примерах: Интерфейсы (Interfaces)
-

Go by Example: Interfaces

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Interfaces are named collections of method -signatures.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "math"
-)
-
- -
-

Here’s a basic interface for geometric shapes.

- -
- -
type geometry interface {
-    area() float64
-    perim() float64
-}
-
- -
-

For our example we’ll implement this interface on -rect and circle types.

- -
- -
type rect struct {
-    width, height float64
-}
-type circle struct {
-    radius float64
-}
-
- -
-

To implement an interface in Go, we just need to -implement all the methods in the interface. Here we -implement geometry on rects.

- -
- -
func (r rect) area() float64 {
-    return r.width * r.height
-}
-func (r rect) perim() float64 {
-    return 2*r.width + 2*r.height
-}
-
- -
-

The implementation for circles.

- -
- -
func (c circle) area() float64 {
-    return math.Pi * c.radius * c.radius
-}
-func (c circle) perim() float64 {
-    return 2 * math.Pi * c.radius
-}
-
- -
-

If a variable has an interface type, then we can call -methods that are in the named interface. Here’s a -generic measure function taking advantage of this -to work on any geometry.

- -
- -
func measure(g geometry) {
-    fmt.Println(g)
-    fmt.Println(g.area())
-    fmt.Println(g.perim())
-}
-
- -
- - - -
func main() {
-    r := rect{width: 3, height: 4}
-    c := circle{radius: 5}
-
- -
-

The circle and rect struct types both -implement the geometry interface so we can use -instances of -these structs as arguments to measure.

- -
- -
    measure(r)
-    measure(c)
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run interfaces.go
-{3 4}
-12
-14
-{5}
-78.53981633974483
-31.41592653589793
-
- -
-

To learn more about Go’s interfaces, check out this -great blog post.

- -
- - -
+

Go в примерах: Интерфейсы (Interfaces)

- Next example: Errors. + Следующий пример: Ошибки (Errors).

diff --git a/public/json b/public/json index e2327ec..9e541cf 100644 --- a/public/json +++ b/public/json @@ -2,7 +2,7 @@ - Go by Example: JSON + Go в примерах: JSON
-

Go by Example: JSON

+

Go в примерах: JSON

-

Go offers built-in support for JSON encoding and -decoding, including to and from built-in and custom -data types.

+

Go предлагает встроенную поддержку кодирования и +декодирования JSON, в том числе встроенных и +пользовательских типов данных.

@@ -43,7 +43,7 @@ data types.

- +
package main
 
@@ -68,8 +68,8 @@ data types.

-

We’ll use these two structs to demonstrate encoding and -decoding of custom types below.

+

Мы будем использовать эти две структуры, для демонстрации +кодирования и декодирования.

@@ -85,8 +85,9 @@ decoding of custom types below.

-

Only exported fields will be encoded/decoded in JSON. -Fields must start with capital letters to be exported.

+

Только экспортируемые поля могут быть кодированы и +декодированы в JSON. Поля должны начинаться с +заглавной буквы.

@@ -114,9 +115,9 @@ Fields must start with capital letters to be exported.

-

First we’ll look at encoding basic data types to -JSON strings. Here are some examples for atomic -values.

+

Для начала мы рассмотрим кодирование данных в +JSON строку. Вот несколько примеров для простых +типов данных.

@@ -169,8 +170,8 @@ values.

-

And here are some for slices and maps, which encode -to JSON arrays and objects as you’d expect.

+

А вот примеры для срезов и карт, которые кодируются +в JSON массивы и объекты, как мы и ожидаем.

@@ -199,10 +200,11 @@ to JSON arrays and objects as you’d expect.

-

The JSON package can automatically encode your -custom data types. It will only include exported -fields in the encoded output and will by default -use those names as the JSON keys.

+

Пакет JSON может автоматически кодировать ваши +пользовательские типы данных. Он будет включать +только экспортируемые поля в закодированный +вывод и по умолчанию будет использовать эти +имена в качестве ключей JSON.

@@ -219,10 +221,10 @@ use those names as the JSON keys.

-

You can use tags on struct field declarations -to customize the encoded JSON key names. Check the -definition of response2 above to see an example -of such tags.

+

Вы можете использовать теги в объявлениях +структурных полей для настройки кодированных имен +ключей JSON. Проверьте определение response2 +выше, чтобы увидеть пример таких тегов.

@@ -239,9 +241,9 @@ of such tags.

-

Now let’s look at decoding JSON data into Go -values. Here’s an example for a generic data -structure.

+

Теперь давайте рассмотрим декодирование данных +JSON в значения Go. Вот пример для общей +структуры данных.

@@ -254,10 +256,10 @@ structure.

-

We need to provide a variable where the JSON -package can put the decoded data. This -map[string]interface{} will hold a map of strings -to arbitrary data types.

+

Нам нужно предоставить переменную, в которую пакет +JSON может поместить декодированные данные. +`map[string]interface{} будет содержать карту +строк для произвольных типов данных.

@@ -270,8 +272,8 @@ to arbitrary data types.

-

Here’s the actual decoding, and a check for -associated errors.

+

Вот фактическое декодирование и проверка на наличие +ошибок.

@@ -287,10 +289,10 @@ associated errors.

-

In order to use the values in the decoded map, -we’ll need to convert them to their appropriate type. -For example here we convert the value in num to -the expected float64 type.

+

Чтобы использовать значения в декодированной карте, +нам нужно преобразовать их в соответствующий тип. +Например, здесь мы конвертируем значение из num +в ожидаемый тип float64.

@@ -304,8 +306,7 @@ the expected float64 type.

-

Accessing nested data requires a series of -conversions.

+

Доступ к вложенным данным требует ряда преобразований.

@@ -320,11 +321,11 @@ conversions.

-

We can also decode JSON into custom data types. -This has the advantages of adding additional -type-safety to our programs and eliminating the -need for type assertions when accessing the decoded -data.

+

Мы также можем декодировать JSON в пользовательские +типы данных. Это дает преимущество добавления +дополнительной безопасности типов в наши программы +и устранения необходимости в определении типрв +при доступе к декодированным данным.

@@ -341,11 +342,12 @@ data.

-

In the examples above we always used bytes and -strings as intermediates between the data and -JSON representation on standard out. We can also -stream JSON encodings directly to os.Writers like -os.Stdout or even HTTP response bodies.

+

В приведенных выше примерах мы всегда использовали +байты и строки в качестве промежуточных звеньев между +данными и представлением JSON на стандартном выходе. +Мы также можем транслировать JSON-кодировки напрямую +в os.Writer, такие как os.Stdout или даже HTTP-тела +ответа.

@@ -391,10 +393,9 @@ stream JSON encodings directly to os.Writers like
-

We’ve covered the basic of JSON in Go here, but check -out the JSON and Go -blog post and JSON package docs -for more.

+

Мы рассмотрели основы JSON в Go, но ознакомьтесь с +публикацией в блоге JSON and Go +и документацией по пакету JSON.

@@ -407,7 +408,7 @@ for more.

- Next example: XML. + Следующий пример: XML.

-

Go by Example: Line Filters

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

A line filter is a common type of program that reads -input on stdin, processes it, and then prints some -derived result to stdout. grep and sed are common -line filters.

- -
- - -
-

Here’s an example line filter in Go that writes a -capitalized version of all input text. You can use this -pattern to write your own Go line filters.

- -
- -
package main
-
- -
- - - -
import (
-    "bufio"
-    "fmt"
-    "os"
-    "strings"
-)
-
- -
- - - -
func main() {
-
- -
-

Wrapping the unbuffered os.Stdin with a buffered -scanner gives us a convenient Scan method that -advances the scanner to the next token; which is -the next line in the default scanner.

- -
- -
    scanner := bufio.NewScanner(os.Stdin)
-
- -
-

Text returns the current token, here the next line, -from the input.

- -
- -
    for scanner.Scan() {
-
- -
- - - -
        ucl := strings.ToUpper(scanner.Text())
-
- -
-

Write out the uppercased line.

- -
- -
        fmt.Println(ucl)
-    }
-
- -
-

Check for errors during Scan. End of file is -expected and not reported by Scan as an error.

- -
- -
    if err := scanner.Err(); err != nil {
-        fmt.Fprintln(os.Stderr, "error:", err)
-        os.Exit(1)
-    }
-}
-
- -
- - - - - - - - - - - - - -
-

To try out our line filter, first make a file with a few -lowercase lines.

- -
- -
$ echo 'hello'   > /tmp/lines
-$ echo 'filter' >> /tmp/lines
-
- -
-

Then use the line filter to get uppercase lines.

- -
- -
$ cat /tmp/lines | go run line-filters.go
-HELLO
-FILTER
-
- -
+

Go в примерах: Строковые фильтры (Line Filters)

- Next example: File Paths. + Следующий пример: Пути к файлам (File Paths).

diff --git a/public/maps b/public/maps index 443efd7..8d69719 100644 --- a/public/maps +++ b/public/maps @@ -2,7 +2,7 @@ - Go by Example: Maps + Go в примерах: Карты (Maps)
-

Go by Example: Maps

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Maps are Go’s built-in associative data type -(sometimes called hashes or dicts in other languages).

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

To create an empty map, use the builtin make: -make(map[key-type]val-type).

- -
- -
    m := make(map[string]int)
-
- -
-

Set key/value pairs using typical name[key] = val -syntax.

- -
- -
    m["k1"] = 7
-    m["k2"] = 13
-
- -
-

Printing a map with e.g. fmt.Println will show all of -its key/value pairs.

- -
- -
    fmt.Println("map:", m)
-
- -
-

Get a value for a key with name[key].

- -
- -
    v1 := m["k1"]
-    fmt.Println("v1: ", v1)
-
- -
-

The builtin len returns the number of key/value -pairs when called on a map.

- -
- -
    fmt.Println("len:", len(m))
-
- -
-

The builtin delete removes key/value pairs from -a map.

- -
- -
    delete(m, "k2")
-    fmt.Println("map:", m)
-
- -
-

The optional second return value when getting a -value from a map indicates if the key was present -in the map. This can be used to disambiguate -between missing keys and keys with zero values -like 0 or "". Here we didn’t need the value -itself, so we ignored it with the blank identifier -_.

- -
- -
    _, prs := m["k2"]
-    fmt.Println("prs:", prs)
-
- -
-

You can also declare and initialize a new map in -the same line with this syntax.

- -
- -
    n := map[string]int{"foo": 1, "bar": 2}
-    fmt.Println("map:", n)
-}
-
- -
- - - - - - - - -
-

Note that maps appear in the form map[k:v k:v] when -printed with fmt.Println.

- -
- -
$ go run maps.go 
-map: map[k1:7 k2:13]
-v1:  7
-len: 2
-map: map[k1:7]
-prs: false
-map: map[bar:2 foo:1]
-
- -
+

Go в примерах: Карты (Maps)

- Next example: Range. + Следующий пример: Ряд (Range).

diff --git a/public/methods b/public/methods index ca0589a..268a326 100644 --- a/public/methods +++ b/public/methods @@ -2,7 +2,7 @@ - Go by Example: Methods + Go в примерах: Методы (Methods)
-

Go by Example: Methods

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go supports methods defined on struct types.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
type rect struct {
-    width, height int
-}
-
- -
-

This area method has a receiver type of *rect.

- -
- -
func (r *rect) area() int {
-    return r.width * r.height
-}
-
- -
-

Methods can be defined for either pointer or value -receiver types. Here’s an example of a value receiver.

- -
- -
func (r rect) perim() int {
-    return 2*r.width + 2*r.height
-}
-
- -
- - - -
func main() {
-    r := rect{width: 10, height: 5}
-
- -
-

Here we call the 2 methods defined for our struct.

- -
- -
    fmt.Println("area: ", r.area())
-    fmt.Println("perim:", r.perim())
-
- -
-

Go automatically handles conversion between values -and pointers for method calls. You may want to use -a pointer receiver type to avoid copying on method -calls or to allow the method to mutate the -receiving struct.

- -
- -
    rp := &r
-    fmt.Println("area: ", rp.area())
-    fmt.Println("perim:", rp.perim())
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run methods.go 
-area:  50
-perim: 30
-area:  50
-perim: 30
-
- -
-

Next we’ll look at Go’s mechanism for grouping and -naming related sets of methods: interfaces.

- -
- - -
+

Go в примерах: Методы (Methods)

- Next example: Interfaces. + Следующий пример: Интерфейсы (Interfaces).

diff --git a/public/multiple-return-values b/public/multiple-return-values index bd16bd1..fc6717b 100644 --- a/public/multiple-return-values +++ b/public/multiple-return-values @@ -2,7 +2,7 @@ - Go by Example: Multiple Return Values + Go в примерах: Функции с множественным возвратом (Multiple Return Values)
-

Go by Example: Multiple Return Values

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go has built-in support for multiple return values. -This feature is used often in idiomatic Go, for example -to return both result and error values from a function.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

The (int, int) in this function signature shows that -the function returns 2 ints.

- -
- -
func vals() (int, int) {
-    return 3, 7
-}
-
- -
- - - -
func main() {
-
- -
-

Here we use the 2 different return values from the -call with multiple assignment.

- -
- -
    a, b := vals()
-    fmt.Println(a)
-    fmt.Println(b)
-
- -
-

If you only want a subset of the returned values, -use the blank identifier _.

- -
- -
    _, c := vals()
-    fmt.Println(c)
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run multiple-return-values.go
-3
-7
-7
-
- -
-

Accepting a variable number of arguments is another nice -feature of Go functions; we’ll look at this next.

- -
- - -
+

Go в примерах: Функции с множественным возвратом (Multiple Return Values)

- Next example: Variadic Functions. + Следующий пример: Функции с переменным числом аргументов (Variadic Functions).

diff --git a/public/mutexes b/public/mutexes index 14d8137..571bd6e 100644 --- a/public/mutexes +++ b/public/mutexes @@ -2,7 +2,7 @@ - Go by Example: Mutexes + Go в примерах: Мьютексы (Mutexes)
-

Go by Example: Mutexes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

In the previous example we saw how to manage simple -counter state using atomic operations. -For more complex state we can use a mutex -to safely access data across multiple goroutines.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "math/rand"
-    "sync"
-    "sync/atomic"
-    "time"
-)
-
- -
- - - -
func main() {
-
- -
-

For our example the state will be a map.

- -
- -
    var state = make(map[int]int)
-
- -
-

This mutex will synchronize access to state.

- -
- -
    var mutex = &sync.Mutex{}
-
- -
-

We’ll keep track of how many read and write -operations we do.

- -
- -
    var readOps uint64
-    var writeOps uint64
-
- -
-

Here we start 100 goroutines to execute repeated -reads against the state, once per millisecond in -each goroutine.

- -
- -
    for r := 0; r < 100; r++ {
-        go func() {
-            total := 0
-            for {
-
- -
-

For each read we pick a key to access, -Lock() the mutex to ensure -exclusive access to the state, read -the value at the chosen key, -Unlock() the mutex, and increment -the readOps count.

- -
- -
                key := rand.Intn(5)
-                mutex.Lock()
-                total += state[key]
-                mutex.Unlock()
-                atomic.AddUint64(&readOps, 1)
-
- -
-

Wait a bit between reads.

- -
- -
                time.Sleep(time.Millisecond)
-            }
-        }()
-    }
-
- -
-

We’ll also start 10 goroutines to simulate writes, -using the same pattern we did for reads.

- -
- -
    for w := 0; w < 10; w++ {
-        go func() {
-            for {
-                key := rand.Intn(5)
-                val := rand.Intn(100)
-                mutex.Lock()
-                state[key] = val
-                mutex.Unlock()
-                atomic.AddUint64(&writeOps, 1)
-                time.Sleep(time.Millisecond)
-            }
-        }()
-    }
-
- -
-

Let the 10 goroutines work on the state and -mutex for a second.

- -
- -
    time.Sleep(time.Second)
-
- -
-

Take and report final operation counts.

- -
- -
    readOpsFinal := atomic.LoadUint64(&readOps)
-    fmt.Println("readOps:", readOpsFinal)
-    writeOpsFinal := atomic.LoadUint64(&writeOps)
-    fmt.Println("writeOps:", writeOpsFinal)
-
- -
-

With a final lock of state, show how it ended up.

- -
- -
    mutex.Lock()
-    fmt.Println("state:", state)
-    mutex.Unlock()
-}
-
- -
- - - - - - - - - - - - - -
-

Running the program shows that we executed about -90,000 total operations against our mutex-synchronized -state.

- -
- -
$ go run mutexes.go
-readOps: 83285
-writeOps: 8320
-state: map[1:97 4:53 0:33 2:15 3:2]
-
- -
-

Next we’ll look at implementing this same state -management task using only goroutines and channels.

- -
- - -
+

Go в примерах: Мьютексы (Mutexes)

- Next example: Stateful Goroutines. + Следующий пример: Управление состоянием горутин (Stateful Goroutines).

diff --git a/public/non-blocking-channel-operations b/public/non-blocking-channel-operations index bbe6d55..754f365 100644 --- a/public/non-blocking-channel-operations +++ b/public/non-blocking-channel-operations @@ -2,7 +2,7 @@ - Go by Example: Non-Blocking Channel Operations + Go в примерах: Неблокируемые операции в каналах (Non-Blocking Channel Operations)
-

Go by Example: Non-Blocking Channel Operations

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Basic sends and receives on channels are blocking. -However, we can use select with a default clause to -implement non-blocking sends, receives, and even -non-blocking multi-way selects.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-    messages := make(chan string)
-    signals := make(chan bool)
-
- -
-

Here’s a non-blocking receive. If a value is -available on messages then select will take -the <-messages case with that value. If not -it will immediately take the default case.

- -
- -
    select {
-    case msg := <-messages:
-        fmt.Println("received message", msg)
-    default:
-        fmt.Println("no message received")
-    }
-
- -
-

A non-blocking send works similarly. Here msg -cannot be sent to the messages channel, because -the channel has no buffer and there is no receiver. -Therefore the default case is selected.

- -
- -
    msg := "hi"
-    select {
-    case messages <- msg:
-        fmt.Println("sent message", msg)
-    default:
-        fmt.Println("no message sent")
-    }
-
- -
-

We can use multiple cases above the default -clause to implement a multi-way non-blocking -select. Here we attempt non-blocking receives -on both messages and signals.

- -
- -
    select {
-    case msg := <-messages:
-        fmt.Println("received message", msg)
-    case sig := <-signals:
-        fmt.Println("received signal", sig)
-    default:
-        fmt.Println("no activity")
-    }
-}
-
- -
- - - - - - - - -
- - - -
$ go run non-blocking-channel-operations.go 
-no message received
-no message sent
-no activity
-
- -
+

Go в примерах: Неблокируемые операции в каналах (Non-Blocking Channel Operations)

- Next example: Closing Channels. + Следующий пример: Закрытие каналов (Closing Channels).

diff --git a/public/number-parsing b/public/number-parsing index 269da85..1cf3b50 100644 --- a/public/number-parsing +++ b/public/number-parsing @@ -2,7 +2,7 @@ - Go by Example: Number Parsing + Go в примерах: Парсинг чисел (Number Parsing)
-

Go by Example: Number Parsing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Parsing numbers from strings is a basic but common task -in many programs; here’s how to do it in Go.

- -
- - -
- - - -
package main
-
- -
-

The built-in package strconv provides the number -parsing.

- -
- -
import (
-    "fmt"
-    "strconv"
-)
-
- -
- - - -
func main() {
-
- -
-

With ParseFloat, this 64 tells how many bits of -precision to parse.

- -
- -
    f, _ := strconv.ParseFloat("1.234", 64)
-    fmt.Println(f)
-
- -
-

For ParseInt, the 0 means infer the base from -the string. 64 requires that the result fit in 64 -bits.

- -
- -
    i, _ := strconv.ParseInt("123", 0, 64)
-    fmt.Println(i)
-
- -
-

ParseInt will recognize hex-formatted numbers.

- -
- -
    d, _ := strconv.ParseInt("0x1c8", 0, 64)
-    fmt.Println(d)
-
- -
-

A ParseUint is also available.

- -
- -
    u, _ := strconv.ParseUint("789", 0, 64)
-    fmt.Println(u)
-
- -
-

Atoi is a convenience function for basic base-10 -int parsing.

- -
- -
    k, _ := strconv.Atoi("135")
-    fmt.Println(k)
-
- -
-

Parse functions return an error on bad input.

- -
- -
    _, e := strconv.Atoi("wat")
-    fmt.Println(e)
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run number-parsing.go 
-1.234
-123
-456
-789
-135
-strconv.ParseInt: parsing "wat": invalid syntax
-
- -
-

Next we’ll look at another common parsing task: URLs.

- -
- - -
+

Go в примерах: Парсинг чисел (Number Parsing)

- Next example: URL Parsing. + Следующий пример: Парсинг URL (URL Parsing).

diff --git a/public/panic b/public/panic index 6a9b834..d393582 100644 --- a/public/panic +++ b/public/panic @@ -2,7 +2,7 @@ - Go by Example: Panic + Go в примерах: Panic
-

Go by Example: Panic

+

Go в примерах: Panic

-

A panic typically means something went unexpectedly -wrong. Mostly we use it to fail fast on errors that -shouldn’t occur during normal operation, or that we -aren’t prepared to handle gracefully.

+

Panic обычно означает, что что-то неожиданно пошло +не так. В основном мы используем его для быстрого +отказа при ошибках, которые не должны возникать во +время нормальной работы, или которые мы не готовы +обрабатывать.

@@ -44,7 +45,7 @@ aren’t prepared to handle gracefully.

- +
package main
 
@@ -77,9 +78,10 @@ aren’t prepared to handle gracefully.

-

We’ll use panic throughout this site to check for -unexpected errors. This is the only program on the -site designed to panic.

+

Мы будем использовать panic на этом сайте, чтобы +проверять наличие неожиданных ошибок. Это +единственная программа на сайте, предназначенная +для паники.

@@ -92,10 +94,11 @@ site designed to panic.

-

A common use of panic is to abort if a function -returns an error value that we don’t know how to -(or want to) handle. Here’s an example of -panicking if we get an unexpected error when creating a new file.

+

Обычное использование panic - это прерывание, +если функция возвращает значение ошибки, которое +мы не знаем, как (или хотим) обрабатывать. Вот +пример panic, если мы получаем неожиданную ошибку +при создании нового файла.

@@ -116,9 +119,9 @@ returns an error value that we don’t know how to
-

Running this program will cause it to panic, print -an error message and goroutine traces, and exit with -a non-zero status.

+

Запуск этой программы вызовет панику, распечатает +сообщение об ошибке и трейс выполнения и завершит +работу с ненулевым статусом.

@@ -148,9 +151,10 @@ a non-zero status.

-

Note that unlike some languages which use exceptions -for handling of many errors, in Go it is idiomatic -to use error-indicating return values wherever possible.

+

Обратите внимание, что в отличие от некоторых языков, +которые используют исключения для обработки +ошибок, в Go привычно использовать возвращающие +значения, указывающие на ошибки.

@@ -163,7 +167,7 @@ to use error-indicating return values wherever possible.

- Next example: Defer. + Следующий пример: Defer.

-

Go by Example: Pointers

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go supports pointers, -allowing you to pass references to values and records -within your program.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

We’ll show how pointers work in contrast to values with -2 functions: zeroval and zeroptr. zeroval has an -int parameter, so arguments will be passed to it by -value. zeroval will get a copy of ival distinct -from the one in the calling function.

- -
- -
func zeroval(ival int) {
-    ival = 0
-}
-
- -
-

zeroptr in contrast has an *int parameter, meaning -that it takes an int pointer. The *iptr code in the -function body then dereferences the pointer from its -memory address to the current value at that address. -Assigning a value to a dereferenced pointer changes the -value at the referenced address.

- -
- -
func zeroptr(iptr *int) {
-    *iptr = 0
-}
-
- -
- - - -
func main() {
-    i := 1
-    fmt.Println("initial:", i)
-
- -
- - - -
    zeroval(i)
-    fmt.Println("zeroval:", i)
-
- -
-

The &i syntax gives the memory address of i, -i.e. a pointer to i.

- -
- -
    zeroptr(&i)
-    fmt.Println("zeroptr:", i)
-
- -
-

Pointers can be printed too.

- -
- -
    fmt.Println("pointer:", &i)
-}
-
- -
- - - - - - - - -
-

zeroval doesn’t change the i in main, but -zeroptr does because it has a reference to -the memory address for that variable.

- -
- -
$ go run pointers.go
-initial: 1
-zeroval: 1
-zeroptr: 0
-pointer: 0x42131100
-
- -
+

Go в примерах: Указатели (Pointers)

- Next example: Structs. + Следующий пример: Структуры (Structs).

diff --git a/public/random-numbers b/public/random-numbers index d3685c5..eb1856a 100644 --- a/public/random-numbers +++ b/public/random-numbers @@ -2,7 +2,7 @@ - Go by Example: Random Numbers + Go в примерах: Случайные числа (Random Numbers)
-

Go by Example: Random Numbers

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go’s math/rand package provides -pseudorandom number -generation.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "math/rand"
-    "time"
-)
-
- -
- - - -
func main() {
-
- -
-

For example, rand.Intn returns a random int n, -0 <= n < 100.

- -
- -
    fmt.Print(rand.Intn(100), ",")
-    fmt.Print(rand.Intn(100))
-    fmt.Println()
-
- -
-

rand.Float64 returns a float64 f, -0.0 <= f < 1.0.

- -
- -
    fmt.Println(rand.Float64())
-
- -
-

This can be used to generate random floats in -other ranges, for example 5.0 <= f' < 10.0.

- -
- -
    fmt.Print((rand.Float64()*5)+5, ",")
-    fmt.Print((rand.Float64() * 5) + 5)
-    fmt.Println()
-
- -
-

The default number generator is deterministic, so it’ll -produce the same sequence of numbers each time by default. -To produce varying sequences, give it a seed that changes. -Note that this is not safe to use for random numbers you -intend to be secret, use crypto/rand for those.

- -
- -
    s1 := rand.NewSource(time.Now().UnixNano())
-    r1 := rand.New(s1)
-
- -
-

Call the resulting rand.Rand just like the -functions on the rand package.

- -
- -
    fmt.Print(r1.Intn(100), ",")
-    fmt.Print(r1.Intn(100))
-    fmt.Println()
-
- -
-

If you seed a source with the same number, it -produces the same sequence of random numbers.

- -
- -
    s2 := rand.NewSource(42)
-    r2 := rand.New(s2)
-    fmt.Print(r2.Intn(100), ",")
-    fmt.Print(r2.Intn(100))
-    fmt.Println()
-    s3 := rand.NewSource(42)
-    r3 := rand.New(s3)
-    fmt.Print(r3.Intn(100), ",")
-    fmt.Print(r3.Intn(100))
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run random-numbers.go
-81,87
-0.6645600532184904
-7.123187485356329,8.434115364335547
-0,28
-5,87
-5,87
-
- -
-

See the math/rand -package docs for references on other random quantities -that Go can provide.

- -
- - -
+

Go в примерах: Случайные числа (Random Numbers)

- Next example: Number Parsing. + Следующий пример: Парсинг чисел (Number Parsing).

diff --git a/public/range b/public/range index f09b0c7..17e52bb 100644 --- a/public/range +++ b/public/range @@ -2,7 +2,7 @@ - Go by Example: Range + Go в примерах: Ряд (Range)
-

Go by Example: Range

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

range iterates over elements in a variety of data -structures. Let’s see how to use range with some -of the data structures we’ve already learned.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

Here we use range to sum the numbers in a slice. -Arrays work like this too.

- -
- -
    nums := []int{2, 3, 4}
-    sum := 0
-    for _, num := range nums {
-        sum += num
-    }
-    fmt.Println("sum:", sum)
-
- -
-

range on arrays and slices provides both the -index and value for each entry. Above we didn’t -need the index, so we ignored it with the -blank identifier _. Sometimes we actually want -the indexes though.

- -
- -
    for i, num := range nums {
-        if num == 3 {
-            fmt.Println("index:", i)
-        }
-    }
-
- -
-

range on map iterates over key/value pairs.

- -
- -
    kvs := map[string]string{"a": "apple", "b": "banana"}
-    for k, v := range kvs {
-        fmt.Printf("%s -> %s\n", k, v)
-    }
-
- -
-

range can also iterate over just the keys of a map.

- -
- -
    for k := range kvs {
-        fmt.Println("key:", k)
-    }
-
- -
-

range on strings iterates over Unicode code -points. The first value is the starting byte index -of the rune and the second the rune itself.

- -
- -
    for i, c := range "go" {
-        fmt.Println(i, c)
-    }
-}
-
- -
- - - - - - - - -
- - - -
$ go run range.go
-sum: 9
-index: 1
-a -> apple
-b -> banana
-key: a
-key: b
-0 103
-1 111
-
- -
+

Go в примерах: Ряд (Range)

- Next example: Functions. + Следующий пример: Функции (Functions).

diff --git a/public/range-over-channels b/public/range-over-channels index 1b7354c..e9724c5 100644 --- a/public/range-over-channels +++ b/public/range-over-channels @@ -2,7 +2,7 @@ - Go by Example: Range over Channels + Go в примерах: Перебор значений из каналов (Range over Channels)
-

Go by Example: Range over Channels

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

In a previous example we saw how for and -range provide iteration over basic data structures. -We can also use this syntax to iterate over -values received from a channel.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

We’ll iterate over 2 values in the queue channel.

- -
- -
    queue := make(chan string, 2)
-    queue <- "one"
-    queue <- "two"
-    close(queue)
-
- -
-

This range iterates over each element as it’s -received from queue. Because we closed the -channel above, the iteration terminates after -receiving the 2 elements.

- -
- -
    for elem := range queue {
-        fmt.Println(elem)
-    }
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run range-over-channels.go
-one
-two
-
- -
-

This example also showed that it’s possible to close -a non-empty channel but still have the remaining -values be received.

- -
- - -
+

Go в примерах: Перебор значений из каналов (Range over Channels)

- Next example: Timers. + Следующий пример: Таймеры (Timers).

diff --git a/public/rate-limiting b/public/rate-limiting index 33dd251..e55807e 100644 --- a/public/rate-limiting +++ b/public/rate-limiting @@ -2,7 +2,7 @@ - Go by Example: Rate Limiting + Go в примерах: Ограничение скорости (Rate Limiting)
-

Go by Example: Rate Limiting

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Rate limiting -is an important mechanism for controlling resource -utilization and maintaining quality of service. Go -elegantly supports rate limiting with goroutines, -channels, and tickers.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
- - - -
func main() {
-
- -
-

First we’ll look at basic rate limiting. Suppose -we want to limit our handling of incoming requests. -We’ll serve these requests off a channel of the -same name.

- -
- -
    requests := make(chan int, 5)
-    for i := 1; i <= 5; i++ {
-        requests <- i
-    }
-    close(requests)
-
- -
-

This limiter channel will receive a value -every 200 milliseconds. This is the regulator in -our rate limiting scheme.

- -
- -
    limiter := time.Tick(200 * time.Millisecond)
-
- -
-

By blocking on a receive from the limiter channel -before serving each request, we limit ourselves to -1 request every 200 milliseconds.

- -
- -
    for req := range requests {
-        <-limiter
-        fmt.Println("request", req, time.Now())
-    }
-
- -
-

We may want to allow short bursts of requests in -our rate limiting scheme while preserving the -overall rate limit. We can accomplish this by -buffering our limiter channel. This burstyLimiter -channel will allow bursts of up to 3 events.

- -
- -
    burstyLimiter := make(chan time.Time, 3)
-
- -
-

Fill up the channel to represent allowed bursting.

- -
- -
    for i := 0; i < 3; i++ {
-        burstyLimiter <- time.Now()
-    }
-
- -
-

Every 200 milliseconds we’ll try to add a new -value to burstyLimiter, up to its limit of 3.

- -
- -
    go func() {
-        for t := range time.Tick(200 * time.Millisecond) {
-            burstyLimiter <- t
-        }
-    }()
-
- -
-

Now simulate 5 more incoming requests. The first -3 of these will benefit from the burst capability -of burstyLimiter.

- -
- -
    burstyRequests := make(chan int, 5)
-    for i := 1; i <= 5; i++ {
-        burstyRequests <- i
-    }
-    close(burstyRequests)
-    for req := range burstyRequests {
-        <-burstyLimiter
-        fmt.Println("request", req, time.Now())
-    }
-}
-
- -
- - - - - - - - - - - - - -
-

Running our program we see the first batch of requests -handled once every ~200 milliseconds as desired.

- -
- -
$ go run rate-limiting.go
-request 1 2012-10-19 00:38:18.687438 +0000 UTC
-request 2 2012-10-19 00:38:18.887471 +0000 UTC
-request 3 2012-10-19 00:38:19.087238 +0000 UTC
-request 4 2012-10-19 00:38:19.287338 +0000 UTC
-request 5 2012-10-19 00:38:19.487331 +0000 UTC
-
- -
-

For the second batch of requests we serve the first -3 immediately because of the burstable rate limiting, -then serve the remaining 2 with ~200ms delays each.

- -
- -
request 1 2012-10-19 00:38:20.487578 +0000 UTC
-request 2 2012-10-19 00:38:20.487645 +0000 UTC
-request 3 2012-10-19 00:38:20.487676 +0000 UTC
-request 4 2012-10-19 00:38:20.687483 +0000 UTC
-request 5 2012-10-19 00:38:20.887542 +0000 UTC
-
- -
+

Go в примерах: Ограничение скорости (Rate Limiting)

- Next example: Atomic Counters. + Следующий пример: Атомарные счетчики (Atomic Counters).

diff --git a/public/reading-files b/public/reading-files index 5f87bee..eeab811 100644 --- a/public/reading-files +++ b/public/reading-files @@ -2,14 +2,14 @@ - Go by Example: Reading Files + Go в примерах: Чтение файлов (Reading Files)
-

Go by Example: Reading Files

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Reading and writing files are basic tasks needed for -many Go programs. First we’ll look at some examples of -reading files.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "bufio"
-    "fmt"
-    "io"
-    "io/ioutil"
-    "os"
-)
-
- -
-

Reading files requires checking most calls for errors. -This helper will streamline our error checks below.

- -
- -
func check(e error) {
-    if e != nil {
-        panic(e)
-    }
-}
-
- -
- - - -
func main() {
-
- -
-

Perhaps the most basic file reading task is -slurping a file’s entire contents into memory.

- -
- -
    dat, err := ioutil.ReadFile("/tmp/dat")
-    check(err)
-    fmt.Print(string(dat))
-
- -
-

You’ll often want more control over how and what -parts of a file are read. For these tasks, start -by Opening a file to obtain an os.File value.

- -
- -
    f, err := os.Open("/tmp/dat")
-    check(err)
-
- -
-

Read some bytes from the beginning of the file. -Allow up to 5 to be read but also note how many -actually were read.

- -
- -
    b1 := make([]byte, 5)
-    n1, err := f.Read(b1)
-    check(err)
-    fmt.Printf("%d bytes: %s\n", n1, string(b1[:n1]))
-
- -
-

You can also Seek to a known location in the file -and Read from there.

- -
- -
    o2, err := f.Seek(6, 0)
-    check(err)
-    b2 := make([]byte, 2)
-    n2, err := f.Read(b2)
-    check(err)
-    fmt.Printf("%d bytes @ %d: ", n2, o2)
-    fmt.Printf("%v\n", string(b2[:n2]))
-
- -
-

The io package provides some functions that may -be helpful for file reading. For example, reads -like the ones above can be more robustly -implemented with ReadAtLeast.

- -
- -
    o3, err := f.Seek(6, 0)
-    check(err)
-    b3 := make([]byte, 2)
-    n3, err := io.ReadAtLeast(f, b3, 2)
-    check(err)
-    fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3))
-
- -
-

There is no built-in rewind, but Seek(0, 0) -accomplishes this.

- -
- -
    _, err = f.Seek(0, 0)
-    check(err)
-
- -
-

The bufio package implements a buffered -reader that may be useful both for its efficiency -with many small reads and because of the additional -reading methods it provides.

- -
- -
    r4 := bufio.NewReader(f)
-    b4, err := r4.Peek(5)
-    check(err)
-    fmt.Printf("5 bytes: %s\n", string(b4))
-
- -
-

Close the file when you’re done (usually this would -be scheduled immediately after Opening with -defer).

- -
- -
    f.Close()
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ echo "hello" > /tmp/dat
-$ echo "go" >>   /tmp/dat
-$ go run reading-files.go
-hello
-go
-5 bytes: hello
-2 bytes @ 6: go
-2 bytes @ 6: go
-5 bytes: hello
-
- -
-

Next we’ll look at writing files.

- -
- - -
+

Go в примерах: Чтение файлов (Reading Files)

- Next example: Writing Files. + Следующий пример: Запись файлов (Writing Files).

diff --git a/public/recursion b/public/recursion index 215d30d..a7bf95e 100644 --- a/public/recursion +++ b/public/recursion @@ -2,7 +2,7 @@ - Go by Example: Recursion + Go в примерах: Рекурсия (Recursion)
-

Go by Example: Recursion

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go supports -recursive functions. -Here’s a classic factorial example.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

This fact function calls itself until it reaches the -base case of fact(0).

- -
- -
func fact(n int) int {
-    if n == 0 {
-        return 1
-    }
-    return n * fact(n-1)
-}
-
- -
- - - -
func main() {
-    fmt.Println(fact(7))
-}
-
- -
- - - - - - - - -
- - - -
$ go run recursion.go 
-5040
-
- -
+

Go в примерах: Рекурсия (Recursion)

- Next example: Pointers. + Следующий пример: Указатели (Pointers).

diff --git a/public/regular-expressions b/public/regular-expressions index 76529e3..700db55 100644 --- a/public/regular-expressions +++ b/public/regular-expressions @@ -2,7 +2,7 @@ - Go by Example: Regular Expressions + Go в примерах: Регулярные выражения (Regular Expressions)
-

Go by Example: Regular Expressions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go offers built-in support for regular expressions. -Here are some examples of common regexp-related tasks -in Go.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "bytes"
-    "fmt"
-    "regexp"
-)
-
- -
- - - -
func main() {
-
- -
-

This tests whether a pattern matches a string.

- -
- -
    match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
-    fmt.Println(match)
-
- -
-

Above we used a string pattern directly, but for -other regexp tasks you’ll need to Compile an -optimized Regexp struct.

- -
- -
    r, _ := regexp.Compile("p([a-z]+)ch")
-
- -
-

Many methods are available on these structs. Here’s -a match test like we saw earlier.

- -
- -
    fmt.Println(r.MatchString("peach"))
-
- -
-

This finds the match for the regexp.

- -
- -
    fmt.Println(r.FindString("peach punch"))
-
- -
-

This also finds the first match but returns the -start and end indexes for the match instead of the -matching text.

- -
- -
    fmt.Println(r.FindStringIndex("peach punch"))
-
- -
-

The Submatch variants include information about -both the whole-pattern matches and the submatches -within those matches. For example this will return -information for both p([a-z]+)ch and ([a-z]+).

- -
- -
    fmt.Println(r.FindStringSubmatch("peach punch"))
-
- -
-

Similarly this will return information about the -indexes of matches and submatches.

- -
- -
    fmt.Println(r.FindStringSubmatchIndex("peach punch"))
-
- -
-

The All variants of these functions apply to all -matches in the input, not just the first. For -example to find all matches for a regexp.

- -
- -
    fmt.Println(r.FindAllString("peach punch pinch", -1))
-
- -
-

These All variants are available for the other -functions we saw above as well.

- -
- -
    fmt.Println(r.FindAllStringSubmatchIndex(
-        "peach punch pinch", -1))
-
- -
-

Providing a non-negative integer as the second -argument to these functions will limit the number -of matches.

- -
- -
    fmt.Println(r.FindAllString("peach punch pinch", 2))
-
- -
-

Our examples above had string arguments and used -names like MatchString. We can also provide -[]byte arguments and drop String from the -function name.

- -
- -
    fmt.Println(r.Match([]byte("peach")))
-
- -
-

When creating constants with regular expressions -you can use the MustCompile variation of -Compile. A plain Compile won’t work for -constants because it has 2 return values.

- -
- -
    r = regexp.MustCompile("p([a-z]+)ch")
-    fmt.Println(r)
-
- -
-

The regexp package can also be used to replace -subsets of strings with other values.

- -
- -
    fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))
-
- -
-

The Func variant allows you to transform matched -text with a given function.

- -
- -
    in := []byte("a peach")
-    out := r.ReplaceAllFunc(in, bytes.ToUpper)
-    fmt.Println(string(out))
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run regular-expressions.go 
-true
-true
-peach
-[0 5]
-[peach ea]
-[0 5 1 3]
-[peach punch pinch]
-[[0 5 1 3] [6 11 7 9] [12 17 13 15]]
-[peach punch]
-true
-p([a-z]+)ch
-a <fruit>
-a PEACH
-
- -
-

For a complete reference on Go regular expressions check -the regexp package docs.

- -
- - -
+

Go в примерах: Регулярные выражения (Regular Expressions)

- Next example: JSON. + Следующий пример: JSON.

diff --git a/public/select b/public/select index 116ac3b..f45e57e 100644 --- a/public/select +++ b/public/select @@ -2,7 +2,7 @@ - Go by Example: Select + Go в примерах: Select
-

Go by Example: Select

+

Go в примерах: Select

-

Go’s select lets you wait on multiple channel -operations. Combining goroutines and channels with -select is a powerful feature of Go.

+

Go’s _select позволяет вам ждать нескольких +операций на канале. Сочетание горутин и каналов +с помощью select’а - мощная функция Go.

@@ -43,7 +43,7 @@ select is a powerful feature of Go.

- +
package main
 
@@ -79,7 +79,8 @@ select is a powerful feature of Go.

-

For our example we’ll select across two channels.

+

В нашем примере мы будем выбирать между двумя +каналами.

@@ -93,9 +94,9 @@ select is a powerful feature of Go.

-

Each channel will receive a value after some amount -of time, to simulate e.g. blocking RPC operations -executing in concurrent goroutines.

+

Каждый канал получит значение через некоторое время, +например, для моделирования блокировки RPC-операций, +выполняемых в параллельных горутинах.

@@ -115,8 +116,9 @@ executing in concurrent goroutines.

-

We’ll use select to await both of these values -simultaneously, printing each one as it arrives.

+

Мы будем использовать select, чтобы ожидать +оба значения одновременно, печатая каждое из +них по мере поступления.

@@ -141,8 +143,8 @@ simultaneously, printing each one as it arrives.

-

We receive the values "one" and then "two" as -expected.

+

Мы получаем значние "one" и потом "two", как +и ожидалось.

@@ -157,9 +159,9 @@ expected.

-

Note that the total execution time is only ~2 seconds -since both the 1 and 2 second Sleeps execute -concurrently.

+

Обратите внимание, что общее время выполнения +составляет всего ~2 секунды, так как и 1, и 2 секунды +Sleeps выполняются одновременно.

@@ -174,7 +176,7 @@ concurrently.

- Next example: Timeouts. + Следующий пример: Тайм-ауты (Timeouts).

+

Go в примерах: Хеш SHA1 (SHA1 Hashes)

+ + +

+ Следующий пример: Кодирование Base64 (Base64 Encoding). +

+ + +
+ + + + diff --git a/public/sha1-hashes b/public/sha1-hashes deleted file mode 100644 index 4db0375..0000000 --- a/public/sha1-hashes +++ /dev/null @@ -1,210 +0,0 @@ - - - - - Go by Example: SHA1 Hashes - - - - -
-

Go by Example: SHA1 Hashes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

SHA1 hashes are -frequently used to compute short identities for binary -or text blobs. For example, the git revision control -system uses SHA1s extensively to -identify versioned files and directories. Here’s how to -compute SHA1 hashes in Go.

- -
- - -
- - - -
package main
-
- -
-

Go implements several hash functions in various -crypto/* packages.

- -
- -
import (
-    "crypto/sha1"
-    "fmt"
-)
-
- -
- - - -
func main() {
-    s := "sha1 this string"
-
- -
-

The pattern for generating a hash is sha1.New(), -sha1.Write(bytes), then sha1.Sum([]byte{}). -Here we start with a new hash.

- -
- -
    h := sha1.New()
-
- -
-

Write expects bytes. If you have a string s, -use []byte(s) to coerce it to bytes.

- -
- -
    h.Write([]byte(s))
-
- -
-

This gets the finalized hash result as a byte -slice. The argument to Sum can be used to append -to an existing byte slice: it usually isn’t needed.

- -
- -
    bs := h.Sum(nil)
-
- -
-

SHA1 values are often printed in hex, for example -in git commits. Use the %x format verb to convert -a hash results to a hex string.

- -
- -
    fmt.Println(s)
-    fmt.Printf("%x\n", bs)
-}
-
- -
- - - - - - - - - - - - - - - - - - -
-

Running the program computes the hash and prints it in -a human-readable hex format.

- -
- -
$ go run sha1-hashes.go
-sha1 this string
-cf23df2207d99a74fbe169e3eba035e633b65d94
-
- -
-

You can compute other hashes using a similar pattern to -the one shown above. For example, to compute MD5 hashes -import crypto/md5 and use md5.New().

- -
- - -
-

Note that if you need cryptographically secure hashes, -you should carefully research -hash strength!

- -
- - -
- - -

- Next example: Base64 Encoding. -

- - -
- - - - diff --git a/public/signals b/public/signals index b0109b5..d4b3432 100644 --- a/public/signals +++ b/public/signals @@ -2,7 +2,7 @@ - Go by Example: Signals + Go в примерах: Сигналы (Signals)
-

Go by Example: Signals

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Sometimes we’d like our Go programs to intelligently -handle Unix signals. -For example, we might want a server to gracefully -shutdown when it receives a SIGTERM, or a command-line -tool to stop processing input if it receives a SIGINT. -Here’s how to handle signals in Go with channels.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "os"
-    "os/signal"
-    "syscall"
-)
-
- -
- - - -
func main() {
-
- -
-

Go signal notification works by sending os.Signal -values on a channel. We’ll create a channel to -receive these notifications (we’ll also make one to -notify us when the program can exit).

- -
- -
    sigs := make(chan os.Signal, 1)
-    done := make(chan bool, 1)
-
- -
-

signal.Notify registers the given channel to -receive notifications of the specified signals.

- -
- -
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
-
- -
-

This goroutine executes a blocking receive for -signals. When it gets one it’ll print it out -and then notify the program that it can finish.

- -
- -
    go func() {
-        sig := <-sigs
-        fmt.Println()
-        fmt.Println(sig)
-        done <- true
-    }()
-
- -
-

The program will wait here until it gets the -expected signal (as indicated by the goroutine -above sending a value on done) and then exit.

- -
- -
    fmt.Println("awaiting signal")
-    <-done
-    fmt.Println("exiting")
-}
-
- -
- - - - - - - - -
-

When we run this program it will block waiting for a -signal. By typing ctrl-C (which the -terminal shows as ^C) we can send a SIGINT signal, -causing the program to print interrupt and then exit.

- -
- -
$ go run signals.go
-awaiting signal
-^C
-interrupt
-exiting
-
- -
+

Go в примерах: Сигналы (Signals)

- Next example: Exit. + Следующий пример: Выход (Exit).

diff --git a/public/slices b/public/slices index ee57572..b264dda 100644 --- a/public/slices +++ b/public/slices @@ -2,7 +2,7 @@ - Go by Example: Slices + Go в примерах: Срезы (Slices)
-

Go by Example: Slices

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Slices are a key data type in Go, giving a more -powerful interface to sequences than arrays.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

Unlike arrays, slices are typed only by the -elements they contain (not the number of elements). -To create an empty slice with non-zero length, use -the builtin make. Here we make a slice of -strings of length 3 (initially zero-valued).

- -
- -
    s := make([]string, 3)
-    fmt.Println("emp:", s)
-
- -
-

We can set and get just like with arrays.

- -
- -
    s[0] = "a"
-    s[1] = "b"
-    s[2] = "c"
-    fmt.Println("set:", s)
-    fmt.Println("get:", s[2])
-
- -
-

len returns the length of the slice as expected.

- -
- -
    fmt.Println("len:", len(s))
-
- -
-

In addition to these basic operations, slices -support several more that make them richer than -arrays. One is the builtin append, which -returns a slice containing one or more new values. -Note that we need to accept a return value from -append as we may get a new slice value.

- -
- -
    s = append(s, "d")
-    s = append(s, "e", "f")
-    fmt.Println("apd:", s)
-
- -
-

Slices can also be copy’d. Here we create an -empty slice c of the same length as s and copy -into c from s.

- -
- -
    c := make([]string, len(s))
-    copy(c, s)
-    fmt.Println("cpy:", c)
-
- -
-

Slices support a “slice” operator with the syntax -slice[low:high]. For example, this gets a slice -of the elements s[2], s[3], and s[4].

- -
- -
    l := s[2:5]
-    fmt.Println("sl1:", l)
-
- -
-

This slices up to (but excluding) s[5].

- -
- -
    l = s[:5]
-    fmt.Println("sl2:", l)
-
- -
-

And this slices up from (and including) s[2].

- -
- -
    l = s[2:]
-    fmt.Println("sl3:", l)
-
- -
-

We can declare and initialize a variable for slice -in a single line as well.

- -
- -
    t := []string{"g", "h", "i"}
-    fmt.Println("dcl:", t)
-
- -
-

Slices can be composed into multi-dimensional data -structures. The length of the inner slices can -vary, unlike with multi-dimensional arrays.

- -
- -
    twoD := make([][]int, 3)
-    for i := 0; i < 3; i++ {
-        innerLen := i + 1
-        twoD[i] = make([]int, innerLen)
-        for j := 0; j < innerLen; j++ {
-            twoD[i][j] = i + j
-        }
-    }
-    fmt.Println("2d: ", twoD)
-}
-
- -
- - - - - - - - - - - - - - - - - - -
-

Note that while slices are different types than arrays, -they are rendered similarly by fmt.Println.

- -
- -
$ go run slices.go
-emp: [  ]
-set: [a b c]
-get: c
-len: 3
-apd: [a b c d e f]
-cpy: [a b c d e f]
-sl1: [c d e]
-sl2: [a b c d e]
-sl3: [c d e f]
-dcl: [g h i]
-2d:  [[0] [1 2] [2 3 4]]
-
- -
-

Check out this great blog post -by the Go team for more details on the design and -implementation of slices in Go.

- -
- - -
-

Now that we’ve seen arrays and slices we’ll look at -Go’s other key builtin data structure: maps.

- -
- - -
+

Go в примерах: Срезы (Slices)

- Next example: Maps. + Следующий пример: Карты (Maps).

diff --git a/public/sorting b/public/sorting index ded8f48..3cc8fc4 100644 --- a/public/sorting +++ b/public/sorting @@ -2,7 +2,7 @@ - Go by Example: Sorting + Go в примерах: Сортировка (Sorting)
-

Go by Example: Sorting

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go’s sort package implements sorting for builtins -and user-defined types. We’ll look at sorting for -builtins first.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "sort"
-)
-
- -
- - - -
func main() {
-
- -
-

Sort methods are specific to the builtin type; -here’s an example for strings. Note that sorting is -in-place, so it changes the given slice and doesn’t -return a new one.

- -
- -
    strs := []string{"c", "a", "b"}
-    sort.Strings(strs)
-    fmt.Println("Strings:", strs)
-
- -
-

An example of sorting ints.

- -
- -
    ints := []int{7, 2, 4}
-    sort.Ints(ints)
-    fmt.Println("Ints:   ", ints)
-
- -
-

We can also use sort to check if a slice is -already in sorted order.

- -
- -
    s := sort.IntsAreSorted(ints)
-    fmt.Println("Sorted: ", s)
-}
-
- -
- - - - - - - - -
-

Running our program prints the sorted string and int -slices and true as the result of our AreSorted test.

- -
- -
$ go run sorting.go
-Strings: [a b c]
-Ints:    [2 4 7]
-Sorted:  true
-
- -
+

Go в примерах: Сортировка (Sorting)

- Next example: Sorting by Functions. + Следующий пример: Сортировка через функции (Sorting by Functions).

-

Go by Example: Sorting by Functions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Sometimes we’ll want to sort a collection by something -other than its natural order. For example, suppose we -wanted to sort strings by their length instead of -alphabetically. Here’s an example of custom sorts -in Go.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "sort"
-)
-
- -
-

In order to sort by a custom function in Go, we need a -corresponding type. Here we’ve created a byLength -type that is just an alias for the builtin []string -type.

- -
- -
type byLength []string
-
- -
-

We implement sort.Interface - Len, Less, and -Swap - on our type so we can use the sort package’s -generic Sort function. Len and Swap -will usually be similar across types and Less will -hold the actual custom sorting logic. In our case we -want to sort in order of increasing string length, so -we use len(s[i]) and len(s[j]) here.

- -
- -
func (s byLength) Len() int {
-    return len(s)
-}
-func (s byLength) Swap(i, j int) {
-    s[i], s[j] = s[j], s[i]
-}
-func (s byLength) Less(i, j int) bool {
-    return len(s[i]) < len(s[j])
-}
-
- -
-

With all of this in place, we can now implement our -custom sort by converting the original fruits slice -to byLength, and then use sort.Sort on that typed -slice.

- -
- -
func main() {
-    fruits := []string{"peach", "banana", "kiwi"}
-    sort.Sort(byLength(fruits))
-    fmt.Println(fruits)
-}
-
- -
- - - - - - - - - - - - - -
-

Running our program shows a list sorted by string -length, as desired.

- -
- -
$ go run sorting-by-functions.go 
-[kiwi peach banana]
-
- -
-

By following this same pattern of creating a custom -type, implementing the three Interface methods on that -type, and then calling sort.Sort on a collection of that -custom type, we can sort Go slices by arbitrary -functions.

- -
- - -
+

Go в примерах: Сортировка через функции (Sorting by Functions)

- Next example: Panic. + Следующий пример: Panic.

diff --git a/public/spawning-processes b/public/spawning-processes index da8dfc5..1cc1f34 100644 --- a/public/spawning-processes +++ b/public/spawning-processes @@ -2,14 +2,14 @@ - Go by Example: Spawning Processes + Go в примерах: Порождающие процессы (Spawning Processes)
-

Go by Example: Spawning Processes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Sometimes our Go programs need to spawn other, non-Go -processes. For example, the syntax highlighting on this -site is implemented -by spawning a pygmentize -process from a Go program. Let’s look at a few examples -of spawning processes from Go.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "io/ioutil"
-    "os/exec"
-)
-
- -
- - - -
func main() {
-
- -
-

We’ll start with a simple command that takes no -arguments or input and just prints something to -stdout. The exec.Command helper creates an object -to represent this external process.

- -
- -
    dateCmd := exec.Command("date")
-
- -
-

.Output is another helper that handles the common -case of running a command, waiting for it to finish, -and collecting its output. If there were no errors, -dateOut will hold bytes with the date info.

- -
- -
    dateOut, err := dateCmd.Output()
-    if err != nil {
-        panic(err)
-    }
-    fmt.Println("> date")
-    fmt.Println(string(dateOut))
-
- -
-

Next we’ll look at a slightly more involved case -where we pipe data to the external process on its -stdin and collect the results from its stdout.

- -
- -
    grepCmd := exec.Command("grep", "hello")
-
- -
-

Here we explicitly grab input/output pipes, start -the process, write some input to it, read the -resulting output, and finally wait for the process -to exit.

- -
- -
    grepIn, _ := grepCmd.StdinPipe()
-    grepOut, _ := grepCmd.StdoutPipe()
-    grepCmd.Start()
-    grepIn.Write([]byte("hello grep\ngoodbye grep"))
-    grepIn.Close()
-    grepBytes, _ := ioutil.ReadAll(grepOut)
-    grepCmd.Wait()
-
- -
-

We ommited error checks in the above example, but -you could use the usual if err != nil pattern for -all of them. We also only collect the StdoutPipe -results, but you could collect the StderrPipe in -exactly the same way.

- -
- -
    fmt.Println("> grep hello")
-    fmt.Println(string(grepBytes))
-
- -
-

Note that when spawning commands we need to -provide an explicitly delineated command and -argument array, vs. being able to just pass in one -command-line string. If you want to spawn a full -command with a string, you can use bash’s -c -option:

- -
- -
    lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
-    lsOut, err := lsCmd.Output()
-    if err != nil {
-        panic(err)
-    }
-    fmt.Println("> ls -a -l -h")
-    fmt.Println(string(lsOut))
-}
-
- -
- - - - - - - - - - - - - - - - - - -
-

The spawned programs return output that is the same -as if we had run them directly from the command-line.

- -
- -
$ go run spawning-processes.go 
-> date
-Wed Oct 10 09:53:11 PDT 2012
-
- -
- - - -
> grep hello
-hello grep
-
- -
- - - -
> ls -a -l -h
-drwxr-xr-x  4 mark 136B Oct 3 16:29 .
-drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
--rw-r--r--  1 mark 1.3K Oct 3 16:28 spawning-processes.go
-
- -
+

Go в примерах: Порождающие процессы (Spawning Processes)

- Next example: Exec'ing Processes. + Следующий пример: Исполняющие процессы (Exec'ing Processes).

diff --git a/public/stateful-goroutines b/public/stateful-goroutines index 80ad0ba..df7ce5a 100644 --- a/public/stateful-goroutines +++ b/public/stateful-goroutines @@ -2,7 +2,7 @@ - Go by Example: Stateful Goroutines + Go в примерах: Управление состоянием горутин (Stateful Goroutines)
-

Go by Example: Stateful Goroutines

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

In the previous example we used explicit locking with -mutexes to synchronize access to shared state -across multiple goroutines. Another option is to use the -built-in synchronization features of goroutines and -channels to achieve the same result. This channel-based -approach aligns with Go’s ideas of sharing memory by -communicating and having each piece of data owned -by exactly 1 goroutine.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "math/rand"
-    "sync/atomic"
-    "time"
-)
-
- -
-

In this example our state will be owned by a single -goroutine. This will guarantee that the data is never -corrupted with concurrent access. In order to read or -write that state, other goroutines will send messages -to the owning goroutine and receive corresponding -replies. These readOp and writeOp structs -encapsulate those requests and a way for the owning -goroutine to respond.

- -
- -
type readOp struct {
-    key  int
-    resp chan int
-}
-type writeOp struct {
-    key  int
-    val  int
-    resp chan bool
-}
-
- -
- - - -
func main() {
-
- -
-

As before we’ll count how many operations we perform.

- -
- -
    var readOps uint64
-    var writeOps uint64
-
- -
-

The reads and writes channels will be used by -other goroutines to issue read and write requests, -respectively.

- -
- -
    reads := make(chan readOp)
-    writes := make(chan writeOp)
-
- -
-

Here is the goroutine that owns the state, which -is a map as in the previous example but now private -to the stateful goroutine. This goroutine repeatedly -selects on the reads and writes channels, -responding to requests as they arrive. A response -is executed by first performing the requested -operation and then sending a value on the response -channel resp to indicate success (and the desired -value in the case of reads).

- -
- -
    go func() {
-        var state = make(map[int]int)
-        for {
-            select {
-            case read := <-reads:
-                read.resp <- state[read.key]
-            case write := <-writes:
-                state[write.key] = write.val
-                write.resp <- true
-            }
-        }
-    }()
-
- -
-

This starts 100 goroutines to issue reads to the -state-owning goroutine via the reads channel. -Each read requires constructing a readOp, sending -it over the reads channel, and the receiving the -result over the provided resp channel.

- -
- -
    for r := 0; r < 100; r++ {
-        go func() {
-            for {
-                read := readOp{
-                    key:  rand.Intn(5),
-                    resp: make(chan int)}
-                reads <- read
-                <-read.resp
-                atomic.AddUint64(&readOps, 1)
-                time.Sleep(time.Millisecond)
-            }
-        }()
-    }
-
- -
-

We start 10 writes as well, using a similar -approach.

- -
- -
    for w := 0; w < 10; w++ {
-        go func() {
-            for {
-                write := writeOp{
-                    key:  rand.Intn(5),
-                    val:  rand.Intn(100),
-                    resp: make(chan bool)}
-                writes <- write
-                <-write.resp
-                atomic.AddUint64(&writeOps, 1)
-                time.Sleep(time.Millisecond)
-            }
-        }()
-    }
-
- -
-

Let the goroutines work for a second.

- -
- -
    time.Sleep(time.Second)
-
- -
-

Finally, capture and report the op counts.

- -
- -
    readOpsFinal := atomic.LoadUint64(&readOps)
-    fmt.Println("readOps:", readOpsFinal)
-    writeOpsFinal := atomic.LoadUint64(&writeOps)
-    fmt.Println("writeOps:", writeOpsFinal)
-}
-
- -
- - - - - - - - - - - - - -
-

Running our program shows that the goroutine-based -state management example completes about 80,000 -total operations.

- -
- -
$ go run stateful-goroutines.go
-readOps: 71708
-writeOps: 7177
-
- -
-

For this particular case the goroutine-based approach -was a bit more involved than the mutex-based one. It -might be useful in certain cases though, for example -where you have other channels involved or when managing -multiple such mutexes would be error-prone. You should -use whichever approach feels most natural, especially -with respect to understanding the correctness of your -program.

- -
- - -
+

Go в примерах: Управление состоянием горутин (Stateful Goroutines)

- Next example: Sorting. + Следующий пример: Сортировка (Sorting).

diff --git a/public/string-formatting b/public/string-formatting index 6616ed0..3e8ab84 100644 --- a/public/string-formatting +++ b/public/string-formatting @@ -2,7 +2,7 @@ - Go by Example: String Formatting + Go в примерах: Форматирование строк (String Formatting)
-

Go by Example: String Formatting

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go offers excellent support for string formatting in -the printf tradition. Here are some examples of -common string formatting tasks.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "os"
-)
-
- -
- - - -
type point struct {
-    x, y int
-}
-
- -
- - - -
func main() {
-
- -
-

Go offers several printing “verbs” designed to -format general Go values. For example, this prints -an instance of our point struct.

- -
- -
    p := point{1, 2}
-    fmt.Printf("%v\n", p)
-
- -
-

If the value is a struct, the %+v variant will -include the struct’s field names.

- -
- -
    fmt.Printf("%+v\n", p)
-
- -
-

The %#v variant prints a Go syntax representation -of the value, i.e. the source code snippet that -would produce that value.

- -
- -
    fmt.Printf("%#v\n", p)
-
- -
-

To print the type of a value, use %T.

- -
- -
    fmt.Printf("%T\n", p)
-
- -
-

Formatting booleans is straight-forward.

- -
- -
    fmt.Printf("%t\n", true)
-
- -
-

There are many options for formatting integers. -Use %d for standard, base-10 formatting.

- -
- -
    fmt.Printf("%d\n", 123)
-
- -
-

This prints a binary representation.

- -
- -
    fmt.Printf("%b\n", 14)
-
- -
-

This prints the character corresponding to the -given integer.

- -
- -
    fmt.Printf("%c\n", 33)
-
- -
-

%x provides hex encoding.

- -
- -
    fmt.Printf("%x\n", 456)
-
- -
-

There are also several formatting options for -floats. For basic decimal formatting use %f.

- -
- -
    fmt.Printf("%f\n", 78.9)
-
- -
-

%e and %E format the float in (slightly -different versions of) scientific notation.

- -
- -
    fmt.Printf("%e\n", 123400000.0)
-    fmt.Printf("%E\n", 123400000.0)
-
- -
-

For basic string printing use %s.

- -
- -
    fmt.Printf("%s\n", "\"string\"")
-
- -
-

To double-quote strings as in Go source, use %q.

- -
- -
    fmt.Printf("%q\n", "\"string\"")
-
- -
-

As with integers seen earlier, %x renders -the string in base-16, with two output characters -per byte of input.

- -
- -
    fmt.Printf("%x\n", "hex this")
-
- -
-

To print a representation of a pointer, use %p.

- -
- -
    fmt.Printf("%p\n", &p)
-
- -
-

When formatting numbers you will often want to -control the width and precision of the resulting -figure. To specify the width of an integer, use a -number after the % in the verb. By default the -result will be right-justified and padded with -spaces.

- -
- -
    fmt.Printf("|%6d|%6d|\n", 12, 345)
-
- -
-

You can also specify the width of printed floats, -though usually you’ll also want to restrict the -decimal precision at the same time with the -width.precision syntax.

- -
- -
    fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
-
- -
-

To left-justify, use the - flag.

- -
- -
    fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
-
- -
-

You may also want to control width when formatting -strings, especially to ensure that they align in -table-like output. For basic right-justified width.

- -
- -
    fmt.Printf("|%6s|%6s|\n", "foo", "b")
-
- -
-

To left-justify use the - flag as with numbers.

- -
- -
    fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
-
- -
-

So far we’ve seen Printf, which prints the -formatted string to os.Stdout. Sprintf formats -and returns a string without printing it anywhere.

- -
- -
    s := fmt.Sprintf("a %s", "string")
-    fmt.Println(s)
-
- -
-

You can format+print to io.Writers other than -os.Stdout using Fprintf.

- -
- -
    fmt.Fprintf(os.Stderr, "an %s\n", "error")
-}
-
- -
- - - - - - - - -
- - - -
$ go run string-formatting.go
-{1 2}
-{x:1 y:2}
-main.point{x:1, y:2}
-main.point
-true
-123
-1110
-!
-1c8
-78.900000
-1.234000e+08
-1.234000E+08
-"string"
-"\"string\""
-6865782074686973
-0x42135100
-|    12|   345|
-|  1.20|  3.45|
-|1.20  |3.45  |
-|   foo|     b|
-|foo   |b     |
-a string
-an error
-
- -
+

Go в примерах: Форматирование строк (String Formatting)

- Next example: Regular Expressions. + Следующий пример: Регулярные выражения (Regular Expressions).

diff --git a/public/string-functions b/public/string-functions index 093c467..04ab05a 100644 --- a/public/string-functions +++ b/public/string-functions @@ -2,7 +2,7 @@ - Go by Example: String Functions + Go в примерах: Строковые функции (String Functions)
-

Go by Example: String Functions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

The standard library’s strings package provides many -useful string-related functions. Here are some examples -to give you a sense of the package.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    s "strings"
-)
-
- -
-

We alias fmt.Println to a shorter name as we’ll use -it a lot below.

- -
- -
var p = fmt.Println
-
- -
- - - -
func main() {
-
- -
-

Here’s a sample of the functions available in -strings. Since these are functions from the -package, not methods on the string object itself, -we need pass the string in question as the first -argument to the function. You can find more -functions in the strings -package docs.

- -
- -
    p("Contains:  ", s.Contains("test", "es"))
-    p("Count:     ", s.Count("test", "t"))
-    p("HasPrefix: ", s.HasPrefix("test", "te"))
-    p("HasSuffix: ", s.HasSuffix("test", "st"))
-    p("Index:     ", s.Index("test", "e"))
-    p("Join:      ", s.Join([]string{"a", "b"}, "-"))
-    p("Repeat:    ", s.Repeat("a", 5))
-    p("Replace:   ", s.Replace("foo", "o", "0", -1))
-    p("Replace:   ", s.Replace("foo", "o", "0", 1))
-    p("Split:     ", s.Split("a-b-c-d-e", "-"))
-    p("ToLower:   ", s.ToLower("TEST"))
-    p("ToUpper:   ", s.ToUpper("test"))
-    p()
-
- -
-

Not part of strings, but worth mentioning here, are -the mechanisms for getting the length of a string in -bytes and getting a byte by index.

- -
- -
    p("Len: ", len("hello"))
-    p("Char:", "hello"[1])
-}
-
- -
-

Note that len and indexing above work at the byte level. -Go uses UTF-8 encoded strings, so this is often useful -as-is. If you’re working with potentially multi-byte -characters you’ll want to use encoding-aware operations. -See strings, bytes, runes and characters in Go -for more information.

- -
- - -
- - - - - - - - - - - - - -
- - - -
$ go run string-functions.go
-Contains:   true
-Count:      2
-HasPrefix:  true
-HasSuffix:  true
-Index:      1
-Join:       a-b
-Repeat:     aaaaa
-Replace:    f00
-Replace:    f0o
-Split:      [a b c d e]
-ToLower:    test
-ToUpper:    TEST
-
- -
- - - -
Len:  5
-Char: 101
-
- -
+

Go в примерах: Строковые функции (String Functions)

- Next example: String Formatting. + Следующий пример: Форматирование строк (String Formatting).

diff --git a/public/structs b/public/structs index 672b214..fadbae1 100644 --- a/public/structs +++ b/public/structs @@ -2,7 +2,7 @@ - Go by Example: Structs + Go в примерах: Структуры (Structs)
-

Go by Example: Structs

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go’s structs are typed collections of fields. -They’re useful for grouping data together to form -records.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

This person struct type has name and age fields.

- -
- -
type person struct {
-    name string
-    age  int
-}
-
- -
-

NewPerson constructs a new person struct with the given name

- -
- -
func NewPerson(name string) *person {
-
- -
-

You can safely return a pointer to local variable -as a local variable will survive the scope of the function.

- -
- -
    p := person{name: name}
-    p.age = 42
-    return &p
-}
-
- -
- - - -
func main() {
-
- -
-

This syntax creates a new struct.

- -
- -
    fmt.Println(person{"Bob", 20})
-
- -
-

You can name the fields when initializing a struct.

- -
- -
    fmt.Println(person{name: "Alice", age: 30})
-
- -
-

Omitted fields will be zero-valued.

- -
- -
    fmt.Println(person{name: "Fred"})
-
- -
-

An & prefix yields a pointer to the struct.

- -
- -
    fmt.Println(&person{name: "Ann", age: 40})
-
- -
-

It’s idiomatic to encapsulate new struct creation in constructor functions

- -
- -
    fmt.Println(NewPerson("Jon"))
-
- -
-

Access struct fields with a dot.

- -
- -
    s := person{name: "Sean", age: 50}
-    fmt.Println(s.name)
-
- -
-

You can also use dots with struct pointers - the -pointers are automatically dereferenced.

- -
- -
    sp := &s
-    fmt.Println(sp.age)
-
- -
-

Structs are mutable.

- -
- -
    sp.age = 51
-    fmt.Println(sp.age)
-}
-
- -
- - - - - - - - -
- - - -
$ go run structs.go
-{Bob 20}
-{Alice 30}
-{Fred 0}
-&{Ann 40}
-Sean
-50
-51
-&{Jon 42}
-
- -
+

Go в примерах: Структуры (Structs)

- Next example: Methods. + Следующий пример: Методы (Methods).

diff --git a/public/switch b/public/switch index f0eff96..4f7cf2f 100644 --- a/public/switch +++ b/public/switch @@ -2,7 +2,7 @@ - Go by Example: Switch + Go в примерах: Switch
-

Go by Example: Switch

+

Go в примерах: Switch

-

Switch statements express conditionals across many -branches.

+

Switch помогает проверять условие в нескольких блоках

@@ -42,7 +41,7 @@ branches.

- +
package main
 
@@ -78,7 +77,7 @@ branches.

-

Here’s a basic switch.

+

Стандартное использование switch.

@@ -100,9 +99,10 @@ branches.

-

You can use commas to separate multiple expressions -in the same case statement. We use the optional -default case in this example as well.

+

Вы можете использовать запятую в качестве разделителя, +для перечисления нескольких значений в case. +Так же в данном примере используется блок +по-умолчанию default.

@@ -120,9 +120,9 @@ in the same case statement. We use the optional
-

switch without an expression is an alternate way -to express if/else logic. Here we also show how the -case expressions can be non-constants.

+

switch без условия аналогичен обычному оператору +if/else по своей логике. Так же в этом примере +что в case можно использовать не только константы.

@@ -141,10 +141,9 @@ to express if/else logic. Here we also show how the
-

A type switch compares types instead of values. You -can use this to discover the type of an interface -value. In this example, the variable t will have the -type corresponding to its clause.

+

В этой конструкции switch сравниваются типы значений. +Вы можете использовать этот прием, для определения +типа значения интерфейса.

@@ -194,7 +193,7 @@ type corresponding to its clause.

- Next example: Arrays. + Следующий пример: Массивы (Arrays).

-

Go by Example: Temporary Files and Directories

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Throughout program execution, we often want to create -data that isn’t needed after the program exits. -Temporary files and directories are useful for this -purpose since they don’t pollute the file system over -time.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "io/ioutil"
-    "os"
-    "path/filepath"
-)
-
- -
- - - -
func check(e error) {
-    if e != nil {
-        panic(e)
-    }
-}
-
- -
- - - -
func main() {
-
- -
-

The easiest way to create a temporary file is by -calling ioutil.TempFile. It creates a file and -opens it for reading and writing. We provide "" -as the first argument, so ioutil.TempFile will -create the file in the default location for our OS.

- -
- -
    f, err := ioutil.TempFile("", "sample")
-    check(err)
-
- -
-

Display the name of the temporary file. On -Unix-based OSes the directory will likely be /tmp. -The file name starts with the prefix given as the -second argument to ioutil.TempFile and the rest -is chosen automatically to ensure that concurrent -calls will always create different file names.

- -
- -
    fmt.Println("Temp file name:", f.Name())
-
- -
-

Clean up the file after we’re done. The OS is -likely to clean up temporary files by itself after -some time, but it’s good practice to do this -explicitly.

- -
- -
    defer os.Remove(f.Name())
-
- -
-

We can write some data to the file.

- -
- -
    _, err = f.Write([]byte{1, 2, 3, 4})
-    check(err)
-
- -
-

If we intend to write many temporary files, we may -prefer to create a temporary directory. -ioutil.TempDir’s arguments are the same as -TempFile’s, but it returns a directory name -rather than an open file.

- -
- -
    dname, err := ioutil.TempDir("", "sampledir")
-    fmt.Println("Temp dir name:", dname)
-
- -
- - - -
    defer os.RemoveAll(dname)
-
- -
-

Now we can synthesize temporary file names by -prefixing them with our temporary directory.

- -
- -
    fname := filepath.Join(dname, "file1")
-    err = ioutil.WriteFile(fname, []byte{1, 2}, 0666)
-    check(err)
-}
-
- -
- - - - - - - - -
- - - -
$ go run temporary-files-and-directories.go
-Temp file name: /tmp/sample610887201
-Temp dir name: /tmp/sampledir898854668
-
- -
+

Go в примерах: Временные файлы и директории (Temporary Files and Directories)

- Next example: Testing. + Следующий пример: Тестирование (Testing).

diff --git a/public/testing b/public/testing index dc0c517..ae3d56f 100644 --- a/public/testing +++ b/public/testing @@ -2,7 +2,7 @@ - Go by Example: Testing + Go в примерах: Тестирование (Testing)
-

Go by Example: Testing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Unit testing is an important part of writing -principled Go programs. The testing package -provides the tools we need to write unit tests -and the go test command runs tests.

- -
- - -
-

For the sake of demonstration, this code is in package -main, but it could be any package. Testing code -typically lives in the same package as the code it tests.

- -
- -
package main
-
- -
- - - -
import (
-    "fmt"
-    "testing"
-)
-
- -
-

We’ll be testing this simple implementation of an -integer minimum. Typically, the code we’re testing -would be in a source file named something like -intutils.go, and the test file for it would then -be named intutils_test.go.

- -
- -
func IntMin(a, b int) int {
-    if a < b {
-        return a
-    } else {
-        return b
-    }
-}
-
- -
-

A test is created by writing a function with a name -beginning with Test.

- -
- -
func TestIntMinBasic(t *testing.T) {
-    ans := IntMin(2, -2)
-    if ans != -2 {
-
- -
-

t.Error* will report test failures but continue -executing the test. t.Fail* will report test -failures and stop the test immediately.

- -
- -
        t.Errorf("IntMin(2, -2) = %d; want -2", ans)
-    }
-}
-
- -
-

Writing tests can be repetitive, so it’s idiomatic to -use a table-driven style, where test inputs and -expected outputs are listed in a table and a single loop -walks over them and performs the test logic.

- -
- -
func TestIntMinTableDriven(t *testing.T) {
-    var tests = []struct {
-        a, b int
-        want int
-    }{
-        {0, 1, 0},
-        {1, 0, 0},
-        {2, -2, -2},
-        {0, -1, -1},
-        {-1, 0, -1},
-    }
-
- -
-

t.Run enables running “subtests”, one for each -table entry. These are shown separately -when executing go test -v.

- -
- -
    for _, tt := range tests {
-
- -
- - - -
        testname := fmt.Sprintf("%d,%d", tt.a, tt.b)
-        t.Run(testname, func(t *testing.T) {
-            ans := IntMin(tt.a, tt.b)
-            if ans != tt.want {
-                t.Errorf("got %d, want %d", ans, tt.want)
-            }
-        })
-    }
-}
-
- -
- - - - - - - - -
-

Run all tests in the current project in verbose mode.

- -
- -
$ go test -v
-== RUN   TestIntMinBasic
---- PASS: TestIntMinBasic (0.00s)
-=== RUN   TestIntMinTableDriven
-=== RUN   TestIntMinTableDriven/0,1
-=== RUN   TestIntMinTableDriven/1,0
-=== RUN   TestIntMinTableDriven/2,-2
-=== RUN   TestIntMinTableDriven/0,-1
-=== RUN   TestIntMinTableDriven/-1,0
---- PASS: TestIntMinTableDriven (0.00s)
-    --- PASS: TestIntMinTableDriven/0,1 (0.00s)
-    --- PASS: TestIntMinTableDriven/1,0 (0.00s)
-    --- PASS: TestIntMinTableDriven/2,-2 (0.00s)
-    --- PASS: TestIntMinTableDriven/0,-1 (0.00s)
-    --- PASS: TestIntMinTableDriven/-1,0 (0.00s)
-PASS
-ok      examples/testing    0.023s
-
- -
+

Go в примерах: Тестирование (Testing)

- Next example: Command-Line Arguments. + Следующий пример: Аргументы командной строки (Command-Line Arguments).

diff --git a/public/tickers b/public/tickers index dd2bb28..e33731e 100644 --- a/public/tickers +++ b/public/tickers @@ -2,7 +2,7 @@ - Go by Example: Tickers + Go в примерах: Тикеры (повторения) (Tickers)
-

Go by Example: Tickers

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Timers are for when you want to do -something once in the future - tickers are for when -you want to do something repeatedly at regular -intervals. Here’s an example of a ticker that ticks -periodically until we stop it.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
- - - -
func main() {
-
- -
-

Tickers use a similar mechanism to timers: a -channel that is sent values. Here we’ll use the -range builtin on the channel to iterate over -the values as they arrive every 500ms.

- -
- -
    ticker := time.NewTicker(500 * time.Millisecond)
-    done := make(chan bool)
-
- -
- - - -
    go func() {
-        for {
-            select {
-            case <-done:
-                return
-            case t := <-ticker.C:
-                fmt.Println("Tick at", t)
-            }
-        }
-    }()
-
- -
-

Tickers can be stopped like timers. Once a ticker -is stopped it won’t receive any more values on its -channel. We’ll stop ours after 1600ms.

- -
- -
    time.Sleep(1600 * time.Millisecond)
-    ticker.Stop()
-    done <- true
-    fmt.Println("Ticker stopped")
-}
-
- -
- - - - - - - - -
-

When we run this program the ticker should tick 3 times -before we stop it.

- -
- -
$ go run tickers.go
-Tick at 2012-09-23 11:29:56.487625 -0700 PDT
-Tick at 2012-09-23 11:29:56.988063 -0700 PDT
-Tick at 2012-09-23 11:29:57.488076 -0700 PDT
-Ticker stopped
-
- -
+

Go в примерах: Тикеры (повторения) (Tickers)

- Next example: Worker Pools. + Следующий пример: Пулы воркеров (Worker Pools).

diff --git a/public/time b/public/time index 12137d8..75f4c6d 100644 --- a/public/time +++ b/public/time @@ -2,7 +2,7 @@ - Go by Example: Time + Go в примерах: Время (Time)
-

Go by Example: Time

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go offers extensive support for times and durations; -here are some examples.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
- - - -
func main() {
-    p := fmt.Println
-
- -
-

We’ll start by getting the current time.

- -
- -
    now := time.Now()
-    p(now)
-
- -
-

You can build a time struct by providing the -year, month, day, etc. Times are always associated -with a Location, i.e. time zone.

- -
- -
    then := time.Date(
-        2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
-    p(then)
-
- -
-

You can extract the various components of the time -value as expected.

- -
- -
    p(then.Year())
-    p(then.Month())
-    p(then.Day())
-    p(then.Hour())
-    p(then.Minute())
-    p(then.Second())
-    p(then.Nanosecond())
-    p(then.Location())
-
- -
-

The Monday-Sunday Weekday is also available.

- -
- -
    p(then.Weekday())
-
- -
-

These methods compare two times, testing if the -first occurs before, after, or at the same time -as the second, respectively.

- -
- -
    p(then.Before(now))
-    p(then.After(now))
-    p(then.Equal(now))
-
- -
-

The Sub methods returns a Duration representing -the interval between two times.

- -
- -
    diff := now.Sub(then)
-    p(diff)
-
- -
-

We can compute the length of the duration in -various units.

- -
- -
    p(diff.Hours())
-    p(diff.Minutes())
-    p(diff.Seconds())
-    p(diff.Nanoseconds())
-
- -
-

You can use Add to advance a time by a given -duration, or with a - to move backwards by a -duration.

- -
- -
    p(then.Add(diff))
-    p(then.Add(-diff))
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run time.go
-2012-10-31 15:50:13.793654 +0000 UTC
-2009-11-17 20:34:58.651387237 +0000 UTC
-2009
-November
-17
-20
-34
-58
-651387237
-UTC
-Tuesday
-true
-false
-false
-25891h15m15.142266763s
-25891.25420618521
-1.5534752523711128e+06
-9.320851514226677e+07
-93208515142266763
-2012-10-31 15:50:13.793654 +0000 UTC
-2006-12-05 01:19:43.509120474 +0000 UTC
-
- -
-

Next we’ll look at the related idea of time relative to -the Unix epoch.

- -
- - -
+

Go в примерах: Время (Time)

- Next example: Epoch. + Следующий пример: Epoch.

diff --git a/public/time-formatting-parsing b/public/time-formatting-parsing index 5c8f266..176c27a 100644 --- a/public/time-formatting-parsing +++ b/public/time-formatting-parsing @@ -2,7 +2,7 @@ - Go by Example: Time Formatting / Parsing + Go в примерах: Форматирование времени (Time Formatting / Parsing)
-

Go by Example: Time Formatting / Parsing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go supports time formatting and parsing via -pattern-based layouts.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
- - - -
func main() {
-    p := fmt.Println
-
- -
-

Here’s a basic example of formatting a time -according to RFC3339, using the corresponding layout -constant.

- -
- -
    t := time.Now()
-    p(t.Format(time.RFC3339))
-
- -
-

Time parsing uses the same layout values as Format.

- -
- -
    t1, e := time.Parse(
-        time.RFC3339,
-        "2012-11-01T22:08:41+00:00")
-    p(t1)
-
- -
-

Format and Parse use example-based layouts. Usually -you’ll use a constant from time for these layouts, but -you can also supply custom layouts. Layouts must use the -reference time Mon Jan 2 15:04:05 MST 2006 to show the -pattern with which to format/parse a given time/string. -The example time must be exactly as shown: the year 2006, -15 for the hour, Monday for the day of the week, etc.

- -
- -
    p(t.Format("3:04PM"))
-    p(t.Format("Mon Jan _2 15:04:05 2006"))
-    p(t.Format("2006-01-02T15:04:05.999999-07:00"))
-    form := "3 04 PM"
-    t2, e := time.Parse(form, "8 41 PM")
-    p(t2)
-
- -
-

For purely numeric representations you can also -use standard string formatting with the extracted -components of the time value.

- -
- -
    fmt.Printf("%d-%02d-%02dT%02d:%02d:%02d-00:00\n",
-        t.Year(), t.Month(), t.Day(),
-        t.Hour(), t.Minute(), t.Second())
-
- -
-

Parse will return an error on malformed input -explaining the parsing problem.

- -
- -
    ansic := "Mon Jan _2 15:04:05 2006"
-    _, e = time.Parse(ansic, "8:41PM")
-    p(e)
-}
-
- -
- - - - - - - - -
- - - -
$ go run time-formatting-parsing.go 
-2014-04-15T18:00:15-07:00
-2012-11-01 22:08:41 +0000 +0000
-6:00PM
-Tue Apr 15 18:00:15 2014
-2014-04-15T18:00:15.161182-07:00
-0000-01-01 20:41:00 +0000 UTC
-2014-04-15T18:00:15-00:00
-parsing time "8:41PM" as "Mon Jan _2 15:04:05 2006": ...
-
- -
+

Go в примерах: Форматирование времени (Time Formatting / Parsing)

- Next example: Random Numbers. + Следующий пример: Случайные числа (Random Numbers).

diff --git a/public/timeouts b/public/timeouts index 39238ed..0ab0267 100644 --- a/public/timeouts +++ b/public/timeouts @@ -2,7 +2,7 @@ - Go by Example: Timeouts + Go в примерах: Тайм-ауты (Timeouts)
-

Go by Example: Timeouts

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Timeouts are important for programs that connect to -external resources or that otherwise need to bound -execution time. Implementing timeouts in Go is easy and -elegant thanks to channels and select.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
- - - -
func main() {
-
- -
-

For our example, suppose we’re executing an external -call that returns its result on a channel c1 -after 2s. Note that the channel is buffered, so the -send in the goroutine is nonblocking. This is a -common pattern to prevent goroutine leaks in case the -channel is never read.

- -
- -
    c1 := make(chan string, 1)
-    go func() {
-        time.Sleep(2 * time.Second)
-        c1 <- "result 1"
-    }()
-
- -
-

Here’s the select implementing a timeout. -res := <-c1 awaits the result and <-Time.After -awaits a value to be sent after the timeout of -1s. Since select proceeds with the first -receive that’s ready, we’ll take the timeout case -if the operation takes more than the allowed 1s.

- -
- -
    select {
-    case res := <-c1:
-        fmt.Println(res)
-    case <-time.After(1 * time.Second):
-        fmt.Println("timeout 1")
-    }
-
- -
-

If we allow a longer timeout of 3s, then the receive -from c2 will succeed and we’ll print the result.

- -
- -
    c2 := make(chan string, 1)
-    go func() {
-        time.Sleep(2 * time.Second)
-        c2 <- "result 2"
-    }()
-    select {
-    case res := <-c2:
-        fmt.Println(res)
-    case <-time.After(3 * time.Second):
-        fmt.Println("timeout 2")
-    }
-}
-
- -
- - - - - - - - -
-

Running this program shows the first operation timing -out and the second succeeding.

- -
- -
$ go run timeouts.go 
-timeout 1
-result 2
-
- -
+

Go в примерах: Тайм-ауты (Timeouts)

- Next example: Non-Blocking Channel Operations. + Следующий пример: Неблокируемые операции в каналах (Non-Blocking Channel Operations).

diff --git a/public/timers b/public/timers index 977afef..20484a9 100644 --- a/public/timers +++ b/public/timers @@ -2,7 +2,7 @@ - Go by Example: Timers + Go в примерах: Таймеры (Timers)
-

Go by Example: Timers

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

We often want to execute Go code at some point in the -future, or repeatedly at some interval. Go’s built-in -timer and ticker features make both of these tasks -easy. We’ll look first at timers and then -at tickers.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
- - - -
func main() {
-
- -
-

Timers represent a single event in the future. You -tell the timer how long you want to wait, and it -provides a channel that will be notified at that -time. This timer will wait 2 seconds.

- -
- -
    timer1 := time.NewTimer(2 * time.Second)
-
- -
-

The <-timer1.C blocks on the timer’s channel C -until it sends a value indicating that the timer -expired.

- -
- -
    <-timer1.C
-    fmt.Println("Timer 1 expired")
-
- -
-

If you just wanted to wait, you could have used -time.Sleep. One reason a timer may be useful is -that you can cancel the timer before it expires. -Here’s an example of that.

- -
- -
    timer2 := time.NewTimer(time.Second)
-    go func() {
-        <-timer2.C
-        fmt.Println("Timer 2 expired")
-    }()
-    stop2 := timer2.Stop()
-    if stop2 {
-        fmt.Println("Timer 2 stopped")
-    }
-}
-
- -
- - - - - - - - -
-

The first timer will expire ~2s after we start the -program, but the second should be stopped before it has -a chance to expire.

- -
- -
$ go run timers.go
-Timer 1 expired
-Timer 2 stopped
-
- -
+

Go в примерах: Таймеры (Timers)

- Next example: Tickers. + Следующий пример: Тикеры (повторения) (Tickers).

diff --git a/public/url b/public/url new file mode 100644 index 0000000..6c42ddc --- /dev/null +++ b/public/url @@ -0,0 +1,41 @@ + + + + + Go в примерах: Парсинг URL (URL Parsing) + + + + +
+

Go в примерах: Парсинг URL (URL Parsing)

+ + +

+ Следующий пример: Хеш SHA1 (SHA1 Hashes). +

+ + +
+ + + + diff --git a/public/url-parsing b/public/url-parsing deleted file mode 100644 index 0cd07f4..0000000 --- a/public/url-parsing +++ /dev/null @@ -1,242 +0,0 @@ - - - - - Go by Example: URL Parsing - - - - -
-

Go by Example: URL Parsing

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

URLs provide a uniform way to locate resources. -Here’s how to parse URLs in Go.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "net"
-    "net/url"
-)
-
- -
- - - -
func main() {
-
- -
-

We’ll parse this example URL, which includes a -scheme, authentication info, host, port, path, -query params, and query fragment.

- -
- -
    s := "postgres://user:pass@host.com:5432/path?k=v#f"
-
- -
-

Parse the URL and ensure there are no errors.

- -
- -
    u, err := url.Parse(s)
-    if err != nil {
-        panic(err)
-    }
-
- -
-

Accessing the scheme is straightforward.

- -
- -
    fmt.Println(u.Scheme)
-
- -
-

User contains all authentication info; call -Username and Password on this for individual -values.

- -
- -
    fmt.Println(u.User)
-    fmt.Println(u.User.Username())
-    p, _ := u.User.Password()
-    fmt.Println(p)
-
- -
-

The Host contains both the hostname and the port, -if present. Use SplitHostPort to extract them.

- -
- -
    fmt.Println(u.Host)
-    host, port, _ := net.SplitHostPort(u.Host)
-    fmt.Println(host)
-    fmt.Println(port)
-
- -
-

Here we extract the path and the fragment after -the #.

- -
- -
    fmt.Println(u.Path)
-    fmt.Println(u.Fragment)
-
- -
-

To get query params in a string of k=v format, -use RawQuery. You can also parse query params -into a map. The parsed query param maps are from -strings to slices of strings, so index into [0] -if you only want the first value.

- -
- -
    fmt.Println(u.RawQuery)
-    m, _ := url.ParseQuery(u.RawQuery)
-    fmt.Println(m)
-    fmt.Println(m["k"][0])
-}
-
- -
- - - - - - - - -
-

Running our URL parsing program shows all the different -pieces that we extracted.

- -
- -
$ go run url-parsing.go 
-postgres
-user:pass
-user
-pass
-host.com:5432
-host.com
-5432
-/path
-f
-k=v
-map[k:[v]]
-v
-
- -
- - -

- Next example: SHA1 Hashes. -

- - -
- - - - diff --git a/public/values b/public/values index eef6bfb..3abd5d6 100644 --- a/public/values +++ b/public/values @@ -2,7 +2,7 @@ - Go by Example: Values + Go в примерах: Типы данных (Values)
-

Go by Example: Values

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Go has various value types including strings, -integers, floats, booleans, etc. Here are a few -basic examples.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

Strings, which can be added together with +.

- -
- -
    fmt.Println("go" + "lang")
-
- -
-

Integers and floats.

- -
- -
    fmt.Println("1+1 =", 1+1)
-    fmt.Println("7.0/3.0 =", 7.0/3.0)
-
- -
-

Booleans, with boolean operators as you’d expect.

- -
- -
    fmt.Println(true && false)
-    fmt.Println(true || false)
-    fmt.Println(!true)
-}
-
- -
- - - - - - - - -
- - - -
$ go run values.go
-golang
-1+1 = 2
-7.0/3.0 = 2.3333333333333335
-false
-true
-false
-
- -
+

Go в примерах: Типы данных (Values)

- Next example: Variables. + Следующий пример: Переменные (Variables).

diff --git a/public/variables b/public/variables index 8ce28a3..cacb411 100644 --- a/public/variables +++ b/public/variables @@ -2,7 +2,7 @@ - Go by Example: Variables + Go в примерах: Переменные (Variables)
-

Go by Example: Variables

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

In Go, variables are explicitly declared and used by -the compiler to e.g. check type-correctness of function -calls.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
- - - -
func main() {
-
- -
-

var declares 1 or more variables.

- -
- -
    var a = "initial"
-    fmt.Println(a)
-
- -
-

You can declare multiple variables at once.

- -
- -
    var b, c int = 1, 2
-    fmt.Println(b, c)
-
- -
-

Go will infer the type of initialized variables.

- -
- -
    var d = true
-    fmt.Println(d)
-
- -
-

Variables declared without a corresponding -initialization are zero-valued. For example, the -zero value for an int is 0.

- -
- -
    var e int
-    fmt.Println(e)
-
- -
-

The := syntax is shorthand for declaring and -initializing a variable, e.g. for -var f string = "apple" in this case.

- -
- -
    f := "apple"
-    fmt.Println(f)
-}
-
- -
- - - - - - - - -
- - - -
$ go run variables.go
-initial
-1 2
-true
-0
-apple
-
- -
+

Go в примерах: Переменные (Variables)

- Next example: Constants. + Следующий пример: Константы (Constants).

diff --git a/public/variadic-functions b/public/variadic-functions index 536970b..53e6729 100644 --- a/public/variadic-functions +++ b/public/variadic-functions @@ -2,7 +2,7 @@ - Go by Example: Variadic Functions + Go в примерах: Функции с переменным числом аргументов (Variadic Functions)
-

Go by Example: Variadic Functions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Variadic functions -can be called with any number of trailing arguments. -For example, fmt.Println is a common variadic -function.

- -
- - -
- - - -
package main
-
- -
- - - -
import "fmt"
-
- -
-

Here’s a function that will take an arbitrary number -of ints as arguments.

- -
- -
func sum(nums ...int) {
-    fmt.Print(nums, " ")
-    total := 0
-    for _, num := range nums {
-        total += num
-    }
-    fmt.Println(total)
-}
-
- -
- - - -
func main() {
-
- -
-

Variadic functions can be called in the usual way -with individual arguments.

- -
- -
    sum(1, 2)
-    sum(1, 2, 3)
-
- -
-

If you already have multiple args in a slice, -apply them to a variadic function using -func(slice...) like this.

- -
- -
    nums := []int{1, 2, 3, 4}
-    sum(nums...)
-}
-
- -
- - - - - - - - - - - - - -
- - - -
$ go run variadic-functions.go 
-[1 2] 3
-[1 2 3] 6
-[1 2 3 4] 10
-
- -
-

Another key aspect of functions in Go is their ability -to form closures, which we’ll look at next.

- -
- - -
+

Go в примерах: Функции с переменным числом аргументов (Variadic Functions)

- Next example: Closures. + Следующий пример: Замыкания (Closures).

diff --git a/public/waitgroups b/public/waitgroups index d8c3f13..11682c0 100644 --- a/public/waitgroups +++ b/public/waitgroups @@ -2,7 +2,7 @@ - Go by Example: WaitGroups + Go в примерах: WaitGroups
-

Go by Example: WaitGroups

+

Go в примерах: WaitGroups

-

To wait for multiple goroutines to finish, we can -use a wait group.

+

Для ожидания выполнения нескольких горутин, мы можем +использовать встроенную конструкцию WaitGroup.

@@ -42,7 +42,7 @@ use a wait group.

- +
package main
 
@@ -67,9 +67,9 @@ use a wait group.

-

This is the function we’ll run in every goroutine. -Note that a WaitGroup must be passed to functions by -pointer.

+

Эта функция, которую мы будем запускать в каждой +горутине. Обратите внимание, что WaitGroup должна +быть передана в функцию по указателю.

@@ -83,7 +83,7 @@ pointer.

-

Sleep to simulate an expensive task.

+

Sleep симулирует тяжелую задачу.

@@ -97,7 +97,7 @@ pointer.

-

Notify the WaitGroup that this worker is done.

+

Оповестить WaitGroup что воркер выполнился

@@ -123,8 +123,8 @@ pointer.

-

This WaitGroup is used to wait for all the -goroutines launched here to finish.

+

Эта WaitGroup используется для ожидания выполнения +всех горутинё запущенных здесь.

@@ -137,8 +137,8 @@ goroutines launched here to finish.

-

Launch several goroutines and increment the WaitGroup -counter for each.

+

Запускаем несколько горутин и инкрементируем счетчик +в WaitGroup для каждой запущенной горутины.

@@ -154,8 +154,9 @@ counter for each.

-

Block until the WaitGroup counter goes back to 0; -all the workers notified they’re done.

+

Блокируем звершение программы до момента, пока +счетчик WaitGroup снова не станет равным 0. +Это будет означать, что все горутины выполнились.

@@ -195,8 +196,8 @@ all the workers notified they’re done.

-

The order of workers starting up and finishing -is likely to be different for each invocation.

+

Порядок воркеров начинающихся и выполненных, вероятно +будет изменяться при каждом запуске.

@@ -209,7 +210,7 @@ is likely to be different for each invocation.

- Next example: Rate Limiting. + Следующий пример: Ограничение скорости (Rate Limiting).

-

Go by Example: Worker Pools

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

In this example we’ll look at how to implement -a worker pool using goroutines and channels.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "fmt"
-    "time"
-)
-
- -
-

Here’s the worker, of which we’ll run several -concurrent instances. These workers will receive -work on the jobs channel and send the corresponding -results on results. We’ll sleep a second per job to -simulate an expensive task.

- -
- -
func worker(id int, jobs <-chan int, results chan<- int) {
-    for j := range jobs {
-        fmt.Println("worker", id, "started  job", j)
-        time.Sleep(time.Second)
-        fmt.Println("worker", id, "finished job", j)
-        results <- j * 2
-    }
-}
-
- -
- - - -
func main() {
-
- -
-

In order to use our pool of workers we need to send -them work and collect their results. We make 2 -channels for this.

- -
- -
    jobs := make(chan int, 100)
-    results := make(chan int, 100)
-
- -
-

This starts up 3 workers, initially blocked -because there are no jobs yet.

- -
- -
    for w := 1; w <= 3; w++ {
-        go worker(w, jobs, results)
-    }
-
- -
-

Here we send 5 jobs and then close that -channel to indicate that’s all the work we have.

- -
- -
    for j := 1; j <= 5; j++ {
-        jobs <- j
-    }
-    close(jobs)
-
- -
-

Finally we collect all the results of the work. -This also ensures that the worker goroutines have -finished. An alternative way to wait for multiple -goroutines is to use a WaitGroup.

- -
- -
    for a := 1; a <= 5; a++ {
-        <-results
-    }
-}
-
- -
- - - - - - - - - - - - - -
-

Our running program shows the 5 jobs being executed by -various workers. The program only takes about 2 seconds -despite doing about 5 seconds of total work because -there are 3 workers operating concurrently.

- -
- -
$ time go run worker-pools.go 
-worker 1 started  job 1
-worker 2 started  job 2
-worker 3 started  job 3
-worker 1 finished job 1
-worker 1 started  job 4
-worker 2 finished job 2
-worker 2 started  job 5
-worker 3 finished job 3
-worker 1 finished job 4
-worker 2 finished job 5
-
- -
- - - -
real    0m2.358s
-
- -
+

Go в примерах: Пулы воркеров (Worker Pools)

- Next example: WaitGroups. + Следующий пример: WaitGroups.

diff --git a/public/writing-files b/public/writing-files index 2969c77..fd622c1 100644 --- a/public/writing-files +++ b/public/writing-files @@ -2,7 +2,7 @@ - Go by Example: Writing Files + Go в примерах: Запись файлов (Writing Files)
-

Go by Example: Writing Files

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Writing files in Go follows similar patterns to the -ones we saw earlier for reading.

- -
- - -
- - - -
package main
-
- -
- - - -
import (
-    "bufio"
-    "fmt"
-    "io/ioutil"
-    "os"
-)
-
- -
- - - -
func check(e error) {
-    if e != nil {
-        panic(e)
-    }
-}
-
- -
- - - -
func main() {
-
- -
-

To start, here’s how to dump a string (or just -bytes) into a file.

- -
- -
    d1 := []byte("hello\ngo\n")
-    err := ioutil.WriteFile("/tmp/dat1", d1, 0644)
-    check(err)
-
- -
-

For more granular writes, open a file for writing.

- -
- -
    f, err := os.Create("/tmp/dat2")
-    check(err)
-
- -
-

It’s idiomatic to defer a Close immediately -after opening a file.

- -
- -
    defer f.Close()
-
- -
-

You can Write byte slices as you’d expect.

- -
- -
    d2 := []byte{115, 111, 109, 101, 10}
-    n2, err := f.Write(d2)
-    check(err)
-    fmt.Printf("wrote %d bytes\n", n2)
-
- -
-

A WriteString is also available.

- -
- -
    n3, err := f.WriteString("writes\n")
-    fmt.Printf("wrote %d bytes\n", n3)
-
- -
-

Issue a Sync to flush writes to stable storage.

- -
- -
    f.Sync()
-
- -
-

bufio provides buffered writers in addition -to the buffered readers we saw earlier.

- -
- -
    w := bufio.NewWriter(f)
-    n4, err := w.WriteString("buffered\n")
-    fmt.Printf("wrote %d bytes\n", n4)
-
- -
-

Use Flush to ensure all buffered operations have -been applied to the underlying writer.

- -
- -
    w.Flush()
-
- -
- - - -
}
-
- -
- - - - - - - - - - - - - - - - - - -
-

Try running the file-writing code.

- -
- -
$ go run writing-files.go 
-wrote 5 bytes
-wrote 7 bytes
-wrote 9 bytes
-
- -
-

Then check the contents of the written files.

- -
- -
$ cat /tmp/dat1
-hello
-go
-$ cat /tmp/dat2
-some
-writes
-buffered
-
- -
-

Next we’ll look at applying some of the file I/O ideas -we’ve just seen to the stdin and stdout streams.

- -
- - -
+

Go в примерах: Запись файлов (Writing Files)

- Next example: Line Filters. + Следующий пример: Строковые фильтры (Line Filters).

diff --git a/public/xml b/public/xml index e463b37..95f1a49 100644 --- a/public/xml +++ b/public/xml @@ -2,7 +2,7 @@ - Go by Example: XML + Go в примерах: XML
-

Go by Example: XML

+

Go в примерах: XML

-

Go offers built-in support for XML and XML-like -formats with the encoding.xml package.

+

Go предлагает встроенную поддержку XML и +XML-подобных форматов с пакетом encoding.xml.

@@ -42,7 +42,7 @@ formats with the encoding.xml package.

- +
package main
 
@@ -66,13 +66,12 @@ formats with the encoding.xml package.

-

This type will be mapped to XML. Similarly to the -JSON examples, field tags contain directives for the -encoder and decoder. Here we use some special features -of the XML package: the XMLName field name dictates -the name of the XML element representing this struct; -id,attr means that the Id field is an XML -attribute rather than a nested element.

+

Этот тип будет сопоставлен с XML. Как и в примерах JSON, +теги полей содержат директивы для кодера и декодера. +Здесь мы используем некоторые особенности пакета XML: +XMLName определяет имя элемента XML, представляющего +эту структуру; id,attr означает, что поле Id является +атрибутом XML, а не вложенным элементом.

@@ -119,9 +118,9 @@ the name of the XML element representing this struct;
-

Emit XML representing our plant; using -MarshalIndent to produce a more -human-readable output.

+

Создаем XML, представляющий наш plant; +использование MarshalIndent для создания более +читабельного вывода.

@@ -135,8 +134,8 @@ human-readable output.

-

To add a generic XML header to the output, append -it explicitly.

+

Чтобы добавить общий заголовок XML к выводу, добавьте +его явно.

@@ -149,10 +148,10 @@ it explicitly.

-

Use Unmarhshal to parse a stream of bytes with XML -into a data structure. If the XML is malformed or -cannot be mapped onto Plant, a descriptive error -will be returned.

+

Используйте Unmarhshal для парсинга байтов с XML в +структуру данных. Если XML имеет неправильный формат +или не может быть преобразован в Plant, будет +возвращена описательная ошибка.

@@ -182,8 +181,9 @@ will be returned.

-

The parent>child>plant field tag tells the encoder -to nest all plants under <parent><child>...

+

Поле parent>child>plant сообщает кодировщику о +необходимости вложения всех plant в +<parent><child>...

@@ -272,7 +272,7 @@ to nest all plants under <parent><child>... - Next example: Time. + Следующий пример: Время (Time).

-

Go by Example

+

Go в примерах

- Go is an - open source programming language designed for - building simple, fast, and reliable software. + Go - это язык программирования с + открытым исходным кодом, предназначенный для создания простого, + быстрого и надежного программного обеспечения.

- Go by Example is a hands-on introduction - to Go using annotated example programs. Check out - the first example or - browse the full list below. + Go в примерах Go by Example - это практическое введение + в Go с использованием примеров реальных программ. Проверьте + первый пример или просмотрите полный + список ниже.

    @@ -28,6 +28,8 @@
diff --git a/tools/generate.go b/tools/generate.go index 7776380..4fd2dd3 100644 --- a/tools/generate.go +++ b/tools/generate.go @@ -238,6 +238,7 @@ func parseAndRenderSegs(sourcePath string) ([]*Seg, string) { func parseExamples() []*Example { var exampleNames []string + re := regexp.MustCompile(`(?m)[a-z0-9]{1}[a-z0-9\-]{1,}[a-z0-9]{1}`) for _, line := range readLines("examples.txt") { if line != "" && !strings.HasPrefix(line, "#") { exampleNames = append(exampleNames, line) @@ -254,7 +255,12 @@ func parseExamples() []*Example { exampleID = strings.Replace(exampleID, "/", "-", -1) exampleID = strings.Replace(exampleID, "'", "", -1) exampleID = dashPat.ReplaceAllString(exampleID, "-") - example.ID = exampleID + + //str := `хеш-sha1-(sha1-hashes)` + //fmt.Println(re.FindString(str)) + + //example.ID = exampleID + example.ID = re.FindString(exampleID) example.Segs = make([][]*Seg, 0) sourcePaths := mustGlob("examples/" + exampleID + "/*") for _, sourcePath := range sourcePaths { @@ -306,6 +312,7 @@ func renderExamples(examples []*Example) { _, err := exampleTmpl.Parse(mustReadFile("templates/example.tmpl")) check(err) for _, example := range examples { + //fmt.Println(example.ID) exampleF, err := os.Create(siteDir + "/" + example.ID) check(err) exampleTmpl.Execute(exampleF, example)